## Utility functions
cat = ''.join
wcat = ' '.join
+lcat = '\n'.join
def pos(letter):
if letter in string.ascii_lowercase:
>>> vigenere_encipher('hello', 'abc')
'hfnlp'
"""
- shifts = [ord(l) - ord('a') for l in sanitise(keyword)]
+ shifts = [pos(l) for l in sanitise(keyword)]
pairs = zip(message, cycle(shifts))
return cat([caesar_encipher_letter(l, k) for l, k in pairs])
>>> vigenere_decipher('hfnlp', 'abc')
'hello'
"""
- shifts = [ord(l) - ord('a') for l in sanitise(keyword)]
+ shifts = [pos(l) for l in sanitise(keyword)]
pairs = zip(message, cycle(shifts))
return cat([caesar_decipher_letter(l, k) for l, k in pairs])
padding = fillvalue[0] * (n - len(sanitised_message) % n)
else:
padding = ''
- message = [ord(c) - ord('a') for c in sanitised_message + padding]
+ message = [pos(c) for c in sanitised_message + padding]
message_chunks = [message[i:i+n] for i in range(0, len(message), n)]
# message_chunks = chunks(message, len(matrix), fillvalue=None)
enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[0]
for c in message_chunks]
- return cat([chr(int(round(l)) % 26 + ord('a'))
+ return cat([unpos(round(l))
for l in sum(enciphered_chunks, [])])
def hill_decipher(matrix, message, fillvalue='a'):
return cat(r_grid[p] for p in pairs1)
+
+def autokey_encipher(message, keyword):
+ """Encipher with the autokey cipher
+
+ >>> autokey_encipher('meetatthefountain', 'kilt')
+ 'wmpmmxxaeyhbryoca'
+ """
+ shifts = [pos(l) for l in keyword + message]
+ pairs = zip(message, shifts)
+ return cat([caesar_encipher_letter(l, k) for l, k in pairs])
+
+def autokey_decipher(ciphertext, keyword):
+ """Decipher with the autokey cipher
+
+ >>> autokey_decipher('wmpmmxxaeyhbryoca', 'kilt')
+ 'meetatthefountain'
+ """
+ plaintext = []
+ keys = list(keyword)
+ for c in ciphertext:
+ plaintext_letter = caesar_decipher_letter(c, pos(keys[0]))
+ plaintext += [plaintext_letter]
+ keys = keys[1:] + [plaintext_letter]
+ return cat(plaintext)
+
+
class PocketEnigma(object):
"""A pocket enigma machine
The wheel is internally represented as a 26-element list self.wheel_map,
self.validate_wheel_spec(wheel)
self.make_wheel_map(wheel)
if position in string.ascii_lowercase:
- self.position = ord(position) - ord('a')
+ self.position = pos(position)
else:
self.position = position
self.validate_wheel_spec(wheel_spec)
self.wheel_map = [0] * 26
for p in wheel_spec:
- self.wheel_map[ord(p[0]) - ord('a')] = ord(p[1]) - ord('a')
- self.wheel_map[ord(p[1]) - ord('a')] = ord(p[0]) - ord('a')
+ self.wheel_map[pos(p[0])] = pos(p[1])
+ self.wheel_map[pos(p[1])] = pos(p[0])
return self.wheel_map
def validate_wheel_spec(self, wheel_spec):
''
"""
if letter in string.ascii_lowercase:
- return chr(
- (self.wheel_map[(ord(letter) - ord('a') - self.position) % 26] +
- self.position) % 26 +
- ord('a'))
+ return unpos(
+ (self.wheel_map[(pos(letter) - self.position) % 26] +
+ self.position))
else:
return ''
>>> pe.set_position('z')
25
"""
- self.position = ord(position) - ord('a')
+ self.position = pos(position)
return self.position