Added new puzzle category, crypto.

This commit is contained in:
Paul S. Ferrell 2009-10-13 10:08:03 -06:00
parent 98f50c3633
commit ed885cafc5
17 changed files with 330 additions and 0 deletions

View File

@ -0,0 +1,16 @@
<dl>
<dt>Alice
<dd>Welcome to Bletchley. It works like this: I'll say something to Bob,
and he'll say something back. Our communication will be encrypted in some
manner, or at least obfuscated. Your job is to get the plaintext, and
find the puzzle key.
<dt>Bob
<dd>Sometimes the plaintext from one puzzle will give you a hint (or the
cryptogaphic key) for the next. When we give you such keys, we'll always
do so in a straightforward manner. The puzzle key for each puzzle
is always in what I say, and there shouldn't be any tricks involved in
figuring out what it is.
<dt>Alice<dd>Good Luck!
<dt>Bob<dd>You'll need it. By the way, the key is 'dirtbags'.
</dl>

1
puzzles/crypto/1/key Normal file
View File

@ -0,0 +1 @@
dirtbags

View File

@ -0,0 +1,3 @@
<dl><dt>Alice<dd>nyy unvy prnfne.
<dt>Bob<dd>prnfne vf gur xrl
</dl>

1
puzzles/crypto/100/key Normal file
View File

@ -0,0 +1 @@
ceasar

View File

@ -0,0 +1,24 @@
plaintext = [b'all hail ceasar.', b'ceasar is the key']
alpha = b'abcdefghijklmnopqrstuvwxyz'
def ceasar(text, r):
out = bytearray()
for t in text:
if t in alpha:
t = t - b'a'[0]
t = (t + r)%26
out.append(t + b'a'[0])
else:
out.append(t)
return bytes(out)
encode = lambda text : ceasar(text, 13)
decode = lambda text : ceasar(text, -13)
c = encode(plaintext[0])
print('<dl><dt>Alice<dd>', str(c, 'utf-8'))
assert decode(c) == plaintext[0]
c = encode(plaintext[1])
print('<dt>Bob<dd>', str(c, 'utf-8'), '</dl>')
assert decode(c) == plaintext[1]

View File

@ -0,0 +1,4 @@
<dl>
<dt>Alice<dd>Vkbd ntg duun puwtvbauwg dbnjwu, hlv bv'd vku dtnu htdbe jpbfebjwud td lduq bf d-hxyud, t vuekfbmlu lduq bf ntfg nxqupf epgjvxcptjkbe twcxpbvnd. Xi exlpdu, bfdvutq xi wuvvup dlhdvbvlvbxf, gxl'pu qxbfc hgvu dlhdvbvlvbxf.
<dt>Bob<dd>Vku fuyv vzx jlsswud tpu t hbv qbiiupufv; vkug tpuf'v 'ufepgjvuq' tv tww. Xk, hg vku ztg, vku oug vkbd vbnu bd: 'vku d bd ixp dleod'.
</dl>

1
puzzles/crypto/110/key Normal file
View File

@ -0,0 +1 @@
the s is for sucks

View File

@ -0,0 +1,48 @@
#!/usr/bin/python3
plaintext = [b"This may seem relatively simple, but it's the same basic "
b"principles as used in s-boxes, a technique used in many modern "
b"cryptographic algoritms. Of course, instead of letter substitution, "
b"you're doing byte substitution.",
b"The next two puzzles are a bit different; Frequency counts (of characters) "
b"will just reveal random noise. "
b"Oh, by the way, the key this time is: 'the s is for sucks'."]
key = b"thequickbrownfxjmpdvlazygs"
def encode(text):
ukey = key.upper()
lkey = key.lower()
assert len(set(key)) == 26, 'invalid key'
assert key.isalpha(), 'non alpha character in key'
out = bytearray()
for t in text:
if t in lkey:
out.append(lkey[t - ord('a')])
elif t in ukey:
out.append(ukey[t - ord('A')])
else:
out.append(t)
return bytes(out)
def decode(text):
ukey = key.upper()
lkey = key.lower()
assert len(set(key)) == 26, 'invalid key'
assert key.isalpha(), 'non alpha character in key'
out = bytearray()
for t in text:
if t in lkey:
out.append(ord('a') + lkey.index(bytes([t])))
elif t in ukey:
out.append(ord('A') + ukey.index(bytes([t])))
else:
out.append(t)
return bytes(out)
c = encode(plaintext[0])
print('<dl><dt>Alice<dd>', str(c, 'utf-8'))
assert decode(c) == plaintext[0]
c = encode(plaintext[1])
print('<dt>Bob<dd>', str(c, 'utf-8'), '</dl>')
assert decode(c) == plaintext[1]

View File

@ -0,0 +1,6 @@
<dl>
<dt>Alice
<dd>KiTvXqBKSkdOiVHAKgyAdZXuTwudIHqzLHcJBCXRPnxCxuxhUmdKcqvNSgkHGgYmKIdQKAOPMatvHAalZzrZcMCFGaiSklvsNsgbLiJmPagZobKLLpgJJcIMDUvKEXFJMiwVbVFKZdjDMKSvTdugBqjPBdlJTlXnDAvFUPNAFpjFESbJNsgJTnCgNeeZIwGfMkmZwnhGCDrOWWYIPafuXZrKNroELoGjXwtQdlSZZwdDTEZxTulhKsAMFthZfHGqSyxnXzdPShkXVrRqDpoNmuTINniddWNvMThBQEWAVbaRLrChBicNXWYbGuwdAQrvLdfdxEJgPErTwysQ
<dt>Bob
<dd>LqItUzQMBgbWoNMNNavSLvNyBStVGUCWNjgQxghYZevZYvWuBcdweBUETsflAiXPPLxBFVHUOrdhFDARCngbRdLnHiytxFnSSpknmEvZDioBdxTRLnlAOcAfPKvODVUWJpstBLmtXskjWuBBHizDKXRtPobcLVyQHjtzKiFFMwzzOVnfHTqZGKKDQinlYgZDHzmWhHEKYwtDMmDiUKrZYARDIoceQDugJhrXVOZnAbbFneByTliWIpTsMWoVGGSAIzpBZXOvIihvSBcjABbCXEZIRblsPxJFUnuXrIDBFphHpFSzUrpsNUzbPXdLNBUAInuJifwtRigMdtzWGkvLAwYqIQmEetyEPSrMHNTBRLtZCJZPRcEdDQdEXdnILAAfNpwzEsVWPUzYJVBCVbUTVojLIviMzWRpMqpQotsYAqtDcFpe
</dl>

1
puzzles/crypto/120/key Normal file
View File

@ -0,0 +1 @@
Rat Fink

View File

@ -0,0 +1,48 @@
#!/usr/bin/python3
"""This is non-obvious, so let me elaborate. The message is translated to
binary with one character per binary bit. Lower case characters are 1's,
and upper case is 0. The letters are chosen at random. Tricky, eh?"""
import random
lower = b'abcdefghijklmnopqrstuvwxyz'
upper = lower.upper()
plaintext = [b'The next puzzle starts in the same way, but the last step is '
b'different.',
b'We wouldn\'t want them to get stuck so early, would we? '
b'Rat Fink']
def encode(text):
out = bytearray()
mask = 0x80
for t in text:
for i in range(8):
if t & mask:
out.append(random.choice(lower))
else:
out.append(random.choice(upper))
t = t << 1
return bytes(out)
def decode(text):
out = bytearray()
i = 0
while i < len(text):
c = 0
mask = 0x80
for j in range(8):
if text[i] in lower:
c = c + mask
mask = mask >> 1
i = i + 1
out.append(c)
return bytes(out)
c = encode(plaintext[0])
print('<dl><dt>Alice<dd>', str(c, 'utf-8'))
assert decode(c) == plaintext[0]
c = encode(plaintext[1])
print('<dt>Bob<dd>', str(c, 'utf-8'), '</dl>')
assert decode(c) == plaintext[1]

View File

@ -0,0 +1,60 @@
#!/usr/bin/python3
'''This is the same as the previous, but it uses non-return to zero to encode
the binary.'''
import random
lower = b'abcdefghijklmnopqrstuvwxyz'
upper = lower.upper()
plaintext = [b'The next one is in Morris Code. Unlike the previous two, '
b'they will actually need to determine some sort of key.',
b'Morris code with a key? That sounds bizarre. probable cause']
def encode(text):
out = bytearray()
mask = 0x80
state = 0
for t in text:
for i in range(8):
next = t & mask
if not state and not next:
out.append(random.choice(upper))
out.append(random.choice(lower))
elif not state and next:
out.append(random.choice(lower))
out.append(random.choice(upper))
elif state and not next:
out.append(random.choice(upper))
out.append(random.choice(lower))
elif state and next:
out.append(random.choice(lower))
out.append(random.choice(upper))
state = next
t = t << 1
return bytes(out)
def decode(text):
out = bytearray()
i = 0
while i < len(text):
c = 0
mask = 0x80
for j in range(8):
a = 0 if text[i] in lower else 1
b = 0 if text[i+1] in lower else 1
assert a != b, 'bad encoding'
if b:
c = c + mask
mask = mask >> 1
i = i + 2
out.append(c)
return bytes(out)
c = encode(plaintext[0])
print('<dl><dt>Alice<dd>', str(c, 'utf-8'))
assert decode(c) == plaintext[0]
c = encode(plaintext[1])
print('<dt>Bob<dd>', str(c, 'utf-8'), '</dl>')
assert decode(c) == plaintext[1]

1
puzzles/crypto/140/key Normal file
View File

@ -0,0 +1 @@
giant chickens

View File

@ -0,0 +1,77 @@
#!/usr/bin/python3
"""This is morris code, except the dots and dashes are each represented by
many different possible characters. The 'encryption key' is the set of
characters that represent dots, and the set that represents dashes."""
import random
dots = b'acdfhkjnpsrtx'
dashes = b'begilmoquvwyz'
morris = {'a': '.-',
'b': '-...',
'c': '-.-.',
'd': '-..',
'e': '.',
'f': '..-.',
'g': '--.',
'h': '....',
'i': '..',
'j': '.---',
'k': '-.-',
'l': '.-..',
'm': '--',
'n': '-.',
'o': '---',
'p': '.--.',
'q': '--.-',
'r': '.-.',
's': '...',
't': '-',
'u': '..-',
'v': '...-',
'w': '.--',
'x': '-..-',
'y': '-.--',
'z': '--..',
'.': '._._._',
',': '--..--',
':': '---...'}
imorris = {}
for k in morris:
imorris[morris[k]] = k
plaintext = [b'It is fun to make up bizarre cyphers, but the next one is '
b'something a little more standard.',
b'All I have to say is: giant chickens.']
def encode(text):
out = bytearray()
for t in text:
if t == ord(' '):
out.append(' ')
else:
for bit in morris[chr(t)]:
if bit == '.':
out.append(random.choice(dots))
else:
out.append(random.choice(dashes))
out.append(' ')
return bytes(out)
def decode(text):
text = text.replace(b' ', b'&')
words = text.split(b'&')
out = bytearray()
for word in words:
for c in word.split(' '):
c = encode(plaintext[0])
print('<dl><dt>Alice<dd>', str(c, 'utf-8'))
assert decode(c) == plaintext[0]
c = encode(plaintext[1])
print('<dt>Bob<dd>', str(c, 'utf-8'), '</dl>')
assert decode(c) == plaintext[1]

1
puzzles/crypto/150/key Normal file
View File

@ -0,0 +1 @@
flaming mastiff

27
puzzles/crypto/150sbox.py Normal file
View File

@ -0,0 +1,27 @@
#!/usr/bin/python3
key = [43, 44, 227, 31, 255, 42, 194, 197, 187, 11, 92, 234, 57, 67, 45, 40, 66, 226, 214, 184, 167, 139, 210, 233, 22, 246, 150, 75, 186, 145, 86, 224, 17, 131, 24, 98, 74, 248, 213, 212, 72, 101, 160, 221, 243, 69, 113, 142, 127, 47, 141, 68, 247, 138, 124, 177, 192, 165, 110, 107, 203, 207, 254, 176, 154, 8, 87, 189, 228, 155, 143, 0, 220, 1, 128, 3, 169, 204, 162, 90, 156, 208, 170, 222, 95, 223, 188, 215, 174, 78, 48, 50, 244, 116, 179, 134, 171, 153, 15, 196, 135, 52, 85, 195, 71, 32, 190, 191, 21, 161, 63, 218, 64, 106, 123, 239, 235, 241, 34, 61, 144, 152, 111, 20, 172, 117, 237, 120, 80, 88, 200, 185, 109, 137, 37, 159, 183, 30, 202, 129, 250, 58, 9, 193, 41, 164, 65, 126, 46, 158, 132, 97, 166, 6, 23, 147, 105, 29, 38, 119, 76, 238, 240, 12, 201, 245, 230, 14, 206, 114, 10, 25, 60, 83, 236, 18, 231, 39, 77, 55, 252, 229, 100, 7, 28, 209, 51, 148, 181, 198, 225, 118, 173, 103, 35, 149, 91, 108, 219, 168, 140, 49, 33, 122, 82, 216, 53, 205, 13, 73, 249, 180, 81, 19, 112, 232, 217, 96, 62, 99, 4, 26, 178, 211, 199, 151, 102, 121, 253, 136, 130, 104, 133, 146, 89, 5, 157, 70, 84, 242, 182, 93, 251, 54, 16, 175, 56, 115, 94, 36, 27, 79, 59, 163, 125, 2]
ikey = [None]*256
for i in range(256):
ikey[key[i]] = i
plaintext = [b'I think it's impressive if they get this one. It will take a '
b'lot of work to get it right. That is, unless they do '
b'something smart like correctly guess the value of spaces. '
b'Frequency counts won't just be your friend here, it'll be '
b'useful in other places too.',
b'I'm not sure if that's enough text to give them the '
b'ability to make a good frequency count. It's nice to '
b'finally be at a real cypher that allows for things like '
b'proper punctuation. Anyway, the key is: flaming mastiff']
def sbox(text, key):
out = bytearray()
for t in text:
out.append(key[t])
return bytes(out)
for p in plaintext:
c = sbox(text, key)
assert c == sbox(c, ikey), 'Failure'
print(c)

11
puzzles/crypto/160xor.py Normal file
View File

@ -0,0 +1,11 @@
#!/usr/bin/python3
plaintext = [b'I wonderr if they'll try doing a frequency count again? '
b'It should work this time as well. Hopefully messing around '
b'with simple cyphers like
for p in plaintext:
c = sbox(text, key)
assert c == sbox(c, ikey), 'Failure'
print(c)