3 CIPHER_ALGORITHMS = ("DES", "DES-EDE3", "BF", "AES-128", "AES-192", "AES-256")
\r
4 CIPHER_MODES = ("CBC", "CFB", "OFB", "ECB")
\r
6 class CipherError(Exception):
\r
11 def __init__(self, libcrypto, cipher_algo, cipher_mode):
\r
12 self.libcrypto = libcrypto
\r
13 self.cipher_algo = cipher_algo
\r
14 self.cipher_mode = cipher_mode
\r
15 cipher_name = "-".join([self.cipher_algo, self.cipher_mode])
\r
16 self.cipher = self.libcrypto.EVP_get_cipherbyname(cipher_name)
\r
17 if self.cipher == 0:
\r
18 raise CipherError, "Unknown cipher: %s" % cipher_name
\r
24 return self.cipher_algo
\r
27 return self.cipher_mode
\r
31 def __init__(self, libcrypto, cipher_type, key, iv, encrypt=True):
\r
32 self.libcrypto = libcrypto
\r
34 key_ptr = c_char_p(key)
\r
35 iv_ptr = c_char_p(iv)
\r
36 self.ctx = self.libcrypto.EVP_CIPHER_CTX_new(cipher_type.cipher, None, key_ptr, iv_ptr)
\r
38 raise CipherError, "Unable to create cipher context"
\r
39 self.encrypt = encrypt
\r
44 result = self.libcrypto.EVP_CipherInit_ex(self.ctx, cipher_type.cipher, None, key_ptr, iv_ptr, c_int(enc))
\r
45 self.cipher_type = cipher_type
\r
48 raise CipherError, "Unable to initialize cipher"
\r
53 def enable_padding(self, padding=True):
\r
58 self.libcrypto.EVP_CIPHER_CTX_set_padding(self.ctx, padding_flag)
\r
60 def update(self, data):
\r
61 if self.cipher_finalized :
\r
62 raise CipherError, "No updates allowed"
\r
63 if type(data) != type(""):
\r
64 raise TypeError, "A string is expected"
\r
67 self.data = self.data + data
\r
69 def finish(self, data=None):
\r
70 if data is not None:
\r
72 return self._finish()
\r
75 if self.cipher_finalized :
\r
76 raise CipherError, "Cipher operation is already completed"
\r
77 self.cipher_out = create_string_buffer(len(self.data) + 32)
\r
78 result = self.libcrypto.EVP_CipherUpdate(self.ctx, byref(self.cipher_out), byref(self.cipher_out_len), c_char_p(self.data), len(self.data))
\r
81 raise CipherError, "Unable to update cipher"
\r
82 self.cipher_finalized = True
\r
83 update_data = self.cipher_out.raw[:self.cipher_out_len.value]
\r
84 result = self.libcrypto.EVP_CipherFinal_ex(self.ctx, byref(self.cipher_out), byref(self.cipher_out_len))
\r
87 raise CipherError, "Unable to finalize cipher"
\r
88 final_data = self.cipher_out.raw[:self.cipher_out_len.value]
\r
89 return update_data + final_data
\r
91 def _clean_ctx(self):
\r
93 if self.ctx is not None:
\r
94 self.libcrypto.EVP_CIPHER_CTX_cleanup(self.ctx)
\r
95 self.libcrypto.EVP_CIPHER_CTX_free(self.ctx)
\r
97 except AttributeError:
\r
99 self.cipher_out = None
\r
100 self.cipher_out_len = c_long(0)
\r
102 self.cipher_finalized = False