Created
December 17, 2011 22:09
-
-
Save codeswimmer/1491559 to your computer and use it in GitHub Desktop.
python: Chaocipher (source: https://bitbucket.org/carver/chaocipher/src/tip/chaocipher.py)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| 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