15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""OpenSSL/M2Crypto 3DES implementation.""" 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from cryptomath import * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from TripleDES import * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if m2cryptoLoaded: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def new(key, mode, IV): 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OpenSSL_TripleDES(key, mode, IV) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class OpenSSL_TripleDES(TripleDES): 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, key, mode, IV): 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TripleDES.__init__(self, key, mode, IV, "openssl") 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.key = key 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.IV = IV 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def _createContext(self, encrypt): 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context = m2.cipher_ctx_new() 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cipherType = m2.des_ede3_cbc() 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m2.cipher_init(context, cipherType, self.key, self.IV, encrypt) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def encrypt(self, plaintext): 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TripleDES.encrypt(self, plaintext) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context = self._createContext(1) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ciphertext = m2.cipher_update(context, plaintext) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m2.cipher_ctx_free(context) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.IV = ciphertext[-self.block_size:] 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ciphertext 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def decrypt(self, ciphertext): 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TripleDES.decrypt(self, ciphertext) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context = self._createContext(0) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #I think M2Crypto has a bug - it fails to decrypt and return the last block passed in. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #To work around this, we append sixteen zeros to the string, below: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) plaintext = m2.cipher_update(context, ciphertext+('\0'*16)) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #If this bug is ever fixed, then plaintext will end up having a garbage 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #plaintext block on the end. That's okay - the below code will ignore it. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) plaintext = plaintext[:len(ciphertext)] 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m2.cipher_ctx_free(context) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.IV = ciphertext[-self.block_size:] 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return plaintext