A very simple keyword encryption algorithm. Produces an encrypted string the same size as the orginal. Not very strong encryption but good enough for lightweight stuff. Works on bytes so could be used for binary streams if converted to and from strings - maybe!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
#PEcrypt - use a string key to encrypt/decrypt another string # - Simon Peverett - January 2004 class PEcrypt: """ PEcrypt - very, very simple word key encryption system uses cyclic XOR between the keyword character bytes and the string to be encrypted/decrypted. Therefore, the same function and keyword will encrypt the string the first time and decrypt it if called on the encrypted string. """ def __init__(self, aKey): """ Initialise the class with the key that is used to encrypt/decrypt strings """ self.key = aKey # CRC can be used to validate a key (very roughly) # if you store the CRC from a previous keyword # and then compare with a newly generated one and # they are the same then chances are the keyword # is correct - only a single byte so not that reliable self.crc = 0 for x in self.key: intX = ord(x) self.crc = self.crc ^ intX def Crypt(self, aString): """ Encrypt/Decrypt the passed string object and return the encrypted string """ kIdx = 0 cryptStr = "" # empty 'crypted string to be returned # loop through the string and XOR each byte with the keyword # to get the 'crypted byte. Add the 'crypted byte to the # 'crypted string for x in range(len(aString)): cryptStr = cryptStr + \ chr( ord(aString[x]) ^ ord(self.key[kIdx])) # use the mod operator - % - to cyclically loop through # the keyword kIdx = (kIdx + 1) % len(self.key) return cryptStr if __name__ == "__main__": def strToHex(aString): hexStr = "" for x in aString: hexStr = hexStr + "%02X " % ord(x) return hexStr # self test routine print "\nTesting PEcrypt!" print "----------------\n" keyStr = "This is a key" testStr = "The quick brown fox jumps over the lazy dog!" print "\nString : ", testStr print "in hex : ", strToHex(testStr) print "key : ", keyStr pe = PEcrypt(keyStr) # generate the PEcrypt instance print "\nPEcrypt CRC = %02X" % pe.crc testStr = pe.Crypt(testStr) print "\nEncrypted string" print "Ascii : ", testStr print "Hex : ", strToHex(testStr) testStr = pe.Crypt(testStr) print "\nDecrypted string" print "Ascii : ", testStr print "Hex : ", strToHex(testStr)
You might want to use this for simple file or comms encryptions.
I had a look at the available encryption modules for Python (see section 15. Cryptographic services of the 2.3.2 on-line documentation) and they were too "heavy". I also looked here in the ASPN cookbook and none of the recipes were quite what I wanted.
Took 30-mins to knock up.
XOR-encryption is very weak. > You might want to use this for simple file or comms encryptions.
You probably don't want to use this -- encryption with XOR is notoriously weak and methods for ciphertext-only cryptanalysis have been around for centuries: do a Google for "Vigenere", a similar scheme based on the 26-letter alphabet.
Lots of good algorithms are at
. If you really need a simple cipher, consider implementing something like RC5 or TEA/XTEA which can be described in just a few lines of code.
(Incidentally, it's faster to build up a string by sticking the pieces in a list and doing a "".join(list), rather than by repeated concatenation.)
XOR and the one-time-pad. XOR encryption is what is used in the "perfect" encryption scheme of the one-time-pad. Use this method with a random key the same length as the message and you have the perfect code -- Just remember to never re-use the key!
Improvements. As a recipe for others to learn from, the original code leaves much to be desired. Foremost, don't build strings with "+" because every addition builds a whole new string (for longer inputs, this O(n**2) behavior is a disaster).
Also, try to not bury the code in comments -- python code is capable of "saying what it does". IOW, don't make something hard out of something simple.
Encryption-wise, it is not wise to transmit the key's CRC because it shrinks the key search space by an order of magnitude.
Instead of Vignere, using the random module is equally pithy but is much harder to crack. If you want the make this revised version even stronger without much effort, then compress the input string with: aString = zlib.compress(aString).
Here is an improved version that is still in the spirit of the original (kept short and sweet instead of complex and secure).
One other thought. Since the conversion is done is a single pass, there in no need to make this a class. Here is a short function that does the trick and adds compression: