1 from ctypes import create_string_buffer,c_char_p,c_void_p,c_int,c_long,byref
\r
2 from ctypescrypto import libcrypto
\r
3 from ctypescryto.exception import LibCrytoError
\r
5 CIPHER_ALGORITHMS = ("DES", "DES-EDE3", "BF", "AES-128", "AES-192", "AES-256")
\r
6 CIPHER_MODES = ("STREAM","ECB","CBC", "CFB", "OFB", "CTR","GCM")
\r
10 class CipherError(LibCryptoError):
\r
13 def new(algname,key,encrypt=True,iv=None):
\r
14 ct=CipherType(algname)
\r
15 return Cipher(ct,key,iv,encrypt)
\r
19 def __init__(self, cipher_name):
\r
20 self.cipher = libcrypto.EVP_get_cipherbyname(cipher_name)
\r
21 if self.cipher is None:
\r
22 raise CipherError, "Unknown cipher: %s" % cipher_name
\r
26 def block_size(self):
\r
27 return libcrypto.EVP_CIHPER_block_size(self.cipher)
\r
28 def key_length(self):
\r
29 return libcrypto.EVP_CIPHER_key_length(self.cipher)
\r
30 def iv_length(self):
\r
31 return libcrypto.EVP_CIPHER_iv_length(self.cipher)
\r
33 return libcrypto.EVP_CIPHER_flags(self.cipher)
\r
35 return CIPHER_MODES[self.flags & 0x7]
\r
37 return self.oid().short_name()
\r
39 return self.cipher_mode
\r
41 return Oid(libcrypto.EVP_CIPHER_nid(self.cipher))
\r
45 def __init__(self, cipher_type, key, iv, encrypt=True):
\r
47 key_ptr = c_char_p(key)
\r
48 iv_ptr = c_char_p(iv)
\r
49 self.ctx = libcrypto.EVP_CIPHER_CTX_new(cipher_type.cipher, None, key_ptr, iv_ptr)
\r
51 raise CipherError, "Unable to create cipher context"
\r
52 self.encrypt = encrypt
\r
57 result = libcrypto.EVP_CipherInit_ex(self.ctx, cipher_type.cipher, None, key_ptr, iv_ptr, c_int(enc))
\r
58 self.cipher_type = cipher_type
\r
59 self.block_size = self.cipher_type.block_size()
\r
62 raise CipherError, "Unable to initialize cipher"
\r
67 def enable_padding(self, padding=True):
\r
72 libcrypto.EVP_CIPHER_CTX_set_padding(self.ctx, padding_flag)
\r
74 def update(self, data):
\r
75 if self.cipher_finalized :
\r
76 raise CipherError, "No updates allowed"
\r
77 if type(data) != type(""):
\r
78 raise TypeError, "A string is expected"
\r
81 outbuf=string_buffer_create(self.blocsize+len(data))
\r
83 ret=libcrypto.EVP_CipherUpdate(self.ctx,outbuf,byref(outlen),
\r
87 self.cipher_finalized=True
\r
89 raise CipherError("problem processing data")
\r
90 return outbuf.raw[:outlen]
\r
93 if self.cipher_finalized :
\r
94 raise CipherError, "Cipher operation is already completed"
\r
95 outbuf=create_string_buffer(self.block_size)
\r
96 self.cipher_finalized = True
\r
97 result = self.libcrypto.EVP_CipherFinal_ex(self.ctx,outbuf , byref(outlen))
\r
100 raise CipherError, "Unable to finalize cipher"
\r
102 return outbuf.raw[:outlen]
\r
106 def _clean_ctx(self):
\r
108 if self.ctx is not None:
\r
109 self.libcrypto.EVP_CIPHER_CTX_cleanup(self.ctx)
\r
110 self.libcrypto.EVP_CIPHER_CTX_free(self.ctx)
\r
112 except AttributeError:
\r
114 self.cipher_finalized = True
\r