Skip to content

Instantly share code, notes, and snippets.

@codeswimmer
Created December 17, 2011 22:09
Show Gist options
  • Select an option

  • Save codeswimmer/1491559 to your computer and use it in GitHub Desktop.

Select an option

Save codeswimmer/1491559 to your computer and use it in GitHub Desktop.
"""
This provides a simple implementation of the 'Chaocipher' encryption
algorithm described at:
http://www.ciphermysteries.com/2010/07/03/the-chaocipher-revealed
Example usage:
import chaocipher
sender = chaocipher.Wheels(CtWheel='QYNBOWTGIRJFEPKLSDMAVZCUXH', PtWheel='JGUACNQLTDHKSOPZFYMXWRVEBI')
receiver = chaocipher.Wheels(CtWheel='QYNBOWTGIRJFEPKLSDMAVZCUXH', PtWheel='JGUACNQLTDHKSOPZFYMXWRVEBI')
cyphertext = sender.encipher("Green eggs and spam")
print "Cyphertext: " + cyphertext
print "Deciphered: " + receiver.decipher(cyphertext)
"""
from string import uppercase #All uppercase letters
class Wheels(object):
def __init__(self, CtWheel='HXUCZVAMDSLKPEFJRIGTWOBNYQ', PtWheel = 'PTLNBQDEOYSFAVZKGJRIHWXUMC'):
#ciphertext alphabet
self.ct = CtWheel[:26].upper()
#plaintext alphabet
self.pt = PtWheel[:26].upper()
#Check we have all the letters in each
for l in uppercase:
if not l in CtWheel:
raise ValueError, "Missing letter(s) in cyphertext wheel"
if not l in PtWheel:
raise ValueError, "Missing letter(s) in plaintext wheel"
def _encipherNext(self, next):
loc = self.pt.index(next)
enciphered = self.ct[loc]
self._permute(loc)
return enciphered
def _decipherNext(self, next):
loc = self.ct.index(next)
deciphered = self.pt[loc]
self._permute(loc)
return deciphered
def _permute(self, loc):
self.ct = self._permuteLeft(self.ct, loc)
self.pt = self._permuteRight(self.pt, loc)
def _permuteLeft(self, wheel, lastCipherPos):
#rotate so last used letter is at front
rotated = wheel[lastCipherPos:] + wheel[:lastCipherPos]
#swap 2nd char to 14th position (1 indexed)
return rotated[0] + rotated[2:14] + rotated[1] + rotated[14:]
def _permuteRight(self, wheel, lastCipherPos):
#rotate so last used letter is at rear
rotated = wheel[lastCipherPos+1:] + wheel[:lastCipherPos+1]
#swap 3rd char to 14th position (1 indexed)
return rotated[0:2] + rotated[3:14] + rotated[2] + rotated[14:]
def encipher(self, text):
"""Encipher some text. This changes the state of the object, so you need
a separate set of Wheels to decipher it."""
text = text.upper()
enciphered = ''
for letter in text:
if letter in uppercase:
enciphered += self._encipherNext(letter)
else:
enciphered += letter #Handle spaces and punctuation
return enciphered
def decipher(self, encrypted):
"""Decipher encrypted text. This changes the state of the Wheels."""
text = encrypted.upper()
deciphered = ''
for letter in text:
if letter in uppercase:
deciphered += self._decipherNext(letter)
else:
deciphered += letter #Handle spaces and punctuation
return deciphered
if __name__ == '__main__':
text = 'WELLDONEISBETTERTHANWELLSAID'
sender = Wheels()
receiver = Wheels() # Separate instances to keep the initial state the same.
enciphered = sender.encipher(text)
print 'enciphered %s to %s' % (text, enciphered)
print 'deciphered %s to %s' % (enciphered, receiver.decipher(enciphered))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment