>> Thanks, this looks very simple too, but where is the decryption code? >> Wikipedia seems to suggest that encryption and decryption are both the >> same but running crypt on the output of crypt doesn't give back the >> original string. So probably I'm misunderstanding something. > > Yes, the nature of a stream cipher :) > > What you're probably doing is what I did, before I had my Aha!!! moment: > > >>>> arc = arcfour("password") >>>> plaintext = "attack at dawn" >>>> ciphertext = arc.crypt(plaintext) >>>> print plaintext; print ciphertext.encode("hex").upper() > attack at dawn > 6371736C6E7C3F495C185629210B >>>> x = arc.crypt(ciphertext) >>>> assert x == plaintext > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > AssertionError >>>> x > '\x16\xf7\xf1\xcc\xda\xb5\xe0\xbf\x0b\x13 bF\x8f' > > > So what's going on? Consider: > > Because Arcfour uses xor for the encryption step, decryption is exactly > the same. So you only need one method to do both. > > But because Arcfour stores state, calling it twice in a row doesn't give > the same result: > >>>> arc.crypt("hello").encode("hex").upper() > 'CAA48DE953' >>>> arc.crypt("hello").encode("hex").upper() > '03405412CA' > > > Arcfour is a stream cipher. When you call it twice on two different > strings, that is logically equivalent to calling it once on a single long > string made up of concatenating the two strings together. Each time you > encrypt a single character, the internal state ("self.s") changes. To > undo the change, you need the same state. The easiest way to do this is > by creating a new instance: > > >>>> encrypter = arcfour("password") >>>> decrypter = arcfour("password") >>>> plaintext = "attack at dawn" >>>> ciphertext = encrypter.crypt(plaintext) >>>> assert decrypter.crypt(ciphertext) == plaintext >>>> > > > So long as the two instances stay in lock-step (every time you use up a > byte from the keystream in one, you do the same in the other) you can use > one to decrypt the output of the other. It doesn't even really matter > which one you use: > >>>> x = decrypter.crypt("Nobody expects the Spanish Inquisition!!!") >>>> encrypter.crypt(x) > 'Nobody expects the Spanish Inquisition!!!' > > > In summary: use the arcfour class to create a stream. If you are just > encrypting, or just decrypting, you can use one stream, or as many > streams as you like, using different keys. But to do both, you need two > streams, initiated with the same key, and kept in lockstep. > > The advantage of a stream cipher is that you can encrypt a text without > needing all the text at once, and then decrypt it the same way: > >>>> output = [] >>>> output.append(encrypt.crypt("abcdefghi")) >>>> output.append(encrypt.crypt("jklmno")) >>>> output.append(encrypt.crypt("p")) >>>> output.append(encrypt.crypt("qrstuvwxyz")) >>>> output = ''.join(output) >>>> >>>> plain = [] >>>> plain.append(decrypt.crypt(output[0:20])) >>>> plain.append(decrypt.crypt(output[20:24])) >>>> plain.append(decrypt.crypt(output[24:])) >>>> ''.join(plain) > 'abcdefghijklmnopqrstuvwxyz'
Thanks Steven, this was very helpful! Cheers, Daniel -- Psss, psss, put it down! - http://www.cafepress.com/putitdown -- http://mail.python.org/mailman/listinfo/python-list