lightweight encryption of text file

Daniel Fetchinson fetchinson at googlemail.com
Sun Jan 10 17:48:02 CET 2010


>> 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



More information about the Python-list mailing list