Skip to content

Commit

Permalink
Merge pull request #2 from HbHbNr/layer3
Browse files Browse the repository at this point in the history
Layer3
  • Loading branch information
HbHbNr authored Aug 26, 2020
2 parents 5ddd31a + 579b346 commit 49f6e9c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 15 deletions.
13 changes: 13 additions & 0 deletions ascii85.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import fileinput

# GNU General Public License Version 3

def decode(a):
Expand Down Expand Up @@ -40,3 +42,14 @@ def decodeTuple(tuple5):
#print(tuple5)
#print(decoded)
return decoded

def loadpayload(inputfile):
payloadmarkerfound = False
payload = []
for line in fileinput.input(inputfile):
if not payloadmarkerfound and line.startswith('<~'):
payloadmarkerfound = True
if payloadmarkerfound:
line = line.strip()
payload.append(line)
return ''.join(payload)
5 changes: 5 additions & 0 deletions ascii85_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

leviathan_encoded = '''<~9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKF<GL>Cj@.4Gp$d7F!,L7@<6@)/0JDEF<G%<+EV:2F!,O<DJ+*.@<*K0@<6L(Df-\\0Ec5e;DffZ(EZee.Bl.9pF"AGXBPCsi+DGm>@3BB/F*&OCAfu2/AKYi(DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIal(DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>uD.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c~>'''
leviathan_plain = 'Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.'
leviathan_file = 'tests/leviathan.txt'

tuples = [('t', 'F8'), ('td', 'FCY'), ('tdo', 'FC]:'), ('tdo!', 'FC];5')]

Expand All @@ -24,3 +25,7 @@ def test_decodeTuple():
assert bytearray(plain, 'utf-8') == ascii85.decodeTuple(encoded.ljust(5, 'u'))[0:len(plain)]
else:
assert False == ascii85.decodeTuple(encoded)

def test_loadpayload():
payload = ascii85.loadpayload(leviathan_file)
assert leviathan_encoded == payload
39 changes: 39 additions & 0 deletions layer3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# GNU General Public License Version 3

def decrypt(decoded):
# beginning of the text is known, leading to the first bytes of the key
expectedstart = bytearray('==[ Layer 4/6: ', 'utf-8')
xor = bytearray()

for i in range(len(expectedstart)):
x = expectedstart[i] ^ decoded[i]
xor.append(x)

# a) 15 * '=' must be in the encrypted text, because the line "==[ Payload ]==" contains 47 * '='.
# b) Multiple occurences are possible, but hopefully in at least one case 17 more '=' will follow.
# c) The last occurence is tried first, because that should be the "Payload"-line.
tattletale = bytearray()
for x in xor:
tattletale.append(x ^ ord('='))
xorfullstart = decoded.rfind(tattletale)

# assumption/hope: the next 32 bytes are all encoded '='
xorfull = bytearray()
for d in decoded[xorfullstart:xorfullstart+32]:
xorfull.append(d ^ ord('='))

# decrypt the bytes with the assumed key
decrypted = bytearray()
for i in range(len(decoded)):
decrypted.append(decoded[i] ^ xorfull[i % 32])

return decrypted


if __name__ == '__main__':
import ascii85

payload = ascii85.loadpayload('layers/layer3.txt')
decoded = ascii85.decode(payload)
decoded = decrypt(decoded)
print(decoded.decode()[0:500])
20 changes: 5 additions & 15 deletions solve.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
import fileinput
import ascii85
import ascii85, layer3

# GNU General Public License Version 3

def loadpayload(inputfile):
payloadmarkerfound = False
payload = []
for line in fileinput.input(inputfile):
if not payloadmarkerfound and line.startswith('<~'):
payloadmarkerfound = True
if payloadmarkerfound:
line = line.strip()
payload.append(line)
return ''.join(payload)

def dumpexcerpt(fulltext, frombegin, fromend):
fulltextlength = len(fulltext)
print(str(fulltextlength) + ' characters of fulltext found')
Expand Down Expand Up @@ -65,17 +53,19 @@ def layer2filtervalid(payload):
divided.append((i >> ((6 - ii) * 8)) & 255)
return divided

for layer in [2]:
for layer in [3]:
inputfile = 'layers/layer' + str(layer) + '.txt'
outputfile = 'layers/layer' + str(layer + 1) + '.txt'

payload = loadpayload(inputfile)
payload = ascii85.loadpayload(inputfile)
dumpexcerpt(payload, 20, 20)
decoded = ascii85.decode(payload)
if layer == 1:
decoded = layer1bitmod(decoded)
elif layer == 2:
decoded = layer2filtervalid(decoded)
elif layer == 3:
decoded = layer3.decrypt(decoded)
#print(decoded[0:100].decode())
#quit()
dumpexcerpt(decoded.decode(), 200, 200)
Expand Down
10 changes: 10 additions & 0 deletions tests/leviathan.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Example from https://en.wikipedia.org/wiki/Ascii85#Example_for_Ascii85

Clear text contains no newlines and reads:
Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.

<~9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKF<GL>Cj@.4Gp$d7F!,L7@<6@)/0JDEF<G%<+EV:2F!,
O<DJ+*.@<*K0@<6L(Df-\0Ec5e;DffZ(EZee.Bl.9pF"AGXBPCsi+DGm>@3BB/F*&OCAfu2/AKY
i(DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIa
l(DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G
>uD.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c~>

0 comments on commit 49f6e9c

Please sign in to comment.