-from ctypes import *\r
+from ctypes import create_string_buffer,c_char_p,c_void_p,c_int,c_long,byref\r
+from ctypescrypto import libcrypto\r
+from ctypescryto.exception import LibCrytoError\r
\r
CIPHER_ALGORITHMS = ("DES", "DES-EDE3", "BF", "AES-128", "AES-192", "AES-256")\r
-CIPHER_MODES = ("CBC", "CFB", "OFB", "ECB")\r
+CIPHER_MODES = ("STREAM","ECB","CBC", "CFB", "OFB", "CTR","GCM")\r
\r
-class CipherError(Exception):\r
+#\r
+\r
+class CipherError(LibCryptoError):\r
pass\r
\r
+def new(algname,key,encrypt=True,iv=None):\r
+ ct=CipherType(algname)\r
+ return Cipher(ct,key,iv,encrypt)\r
+\r
class CipherType:\r
\r
- def __init__(self, libcrypto, cipher_algo, cipher_mode):\r
- self.libcrypto = libcrypto\r
- self.cipher_algo = cipher_algo\r
- self.cipher_mode = cipher_mode\r
- cipher_name = "-".join([self.cipher_algo, self.cipher_mode])\r
- self.cipher = self.libcrypto.EVP_get_cipherbyname(cipher_name)\r
- if self.cipher == 0:\r
+ def __init__(self, cipher_name):\r
+ self.cipher = libcrypto.EVP_get_cipherbyname(cipher_name)\r
+ if self.cipher is None:\r
raise CipherError, "Unknown cipher: %s" % cipher_name\r
\r
def __del__(self):\r
pass\r
-\r
+ def block_size(self):\r
+ return libcrypto.EVP_CIHPER_block_size(self.cipher)\r
+ def key_length(self):\r
+ return libcrypto.EVP_CIPHER_key_length(self.cipher)\r
+ def iv_length(self):\r
+ return libcrypto.EVP_CIPHER_iv_length(self.cipher)\r
+ def flags(self):\r
+ return libcrypto.EVP_CIPHER_flags(self.cipher)\r
+ def mode(self):\r
+ return CIPHER_MODES[self.flags & 0x7]\r
def algo(self):\r
- return self.cipher_algo\r
-\r
+ return self.oid().short_name() \r
def mode(self):\r
return self.cipher_mode\r
+ def oid(self):\r
+ return Oid(libcrypto.EVP_CIPHER_nid(self.cipher))\r
\r
class Cipher:\r
\r
- def __init__(self, libcrypto, cipher_type, key, iv, encrypt=True):\r
- self.libcrypto = libcrypto\r
+ def __init__(self, cipher_type, key, iv, encrypt=True):\r
self._clean_ctx()\r
key_ptr = c_char_p(key)\r
iv_ptr = c_char_p(iv)\r
- self.ctx = self.libcrypto.EVP_CIPHER_CTX_new(cipher_type.cipher, None, key_ptr, iv_ptr)\r
+ self.ctx = libcrypto.EVP_CIPHER_CTX_new(cipher_type.cipher, None, key_ptr, iv_ptr)\r
if self.ctx == 0:\r
raise CipherError, "Unable to create cipher context"\r
self.encrypt = encrypt\r
enc = 1\r
else: \r
enc = 0\r
- result = self.libcrypto.EVP_CipherInit_ex(self.ctx, cipher_type.cipher, None, key_ptr, iv_ptr, c_int(enc))\r
+ result = libcrypto.EVP_CipherInit_ex(self.ctx, cipher_type.cipher, None, key_ptr, iv_ptr, c_int(enc))\r
self.cipher_type = cipher_type\r
+ self.block_size = self.cipher_type.block_size()\r
if result == 0:\r
self._clean_ctx()\r
raise CipherError, "Unable to initialize cipher"\r
padding_flag = 1\r
else:\r
padding_flag = 0\r
- self.libcrypto.EVP_CIPHER_CTX_set_padding(self.ctx, padding_flag)\r
+ libcrypto.EVP_CIPHER_CTX_set_padding(self.ctx, padding_flag)\r
\r
def update(self, data):\r
if self.cipher_finalized :\r
raise TypeError, "A string is expected"\r
if len(data) <= 0:\r
return ""\r
- self.data = self.data + data\r
+ outbuf=string_buffer_create(self.blocsize+len(data))\r
+ outlen=c_int(0)\r
+ ret=libcrypto.EVP_CipherUpdate(self.ctx,outbuf,byref(outlen),\r
+ data,len(data))\r
+ if ret <=0:\r
+ self._clean_ctx()\r
+ self.cipher_finalized=True\r
+ del self.ctx\r
+ raise CipherError("problem processing data")\r
+ return outbuf.raw[:outlen]\r
\r
- def finish(self, data=None):\r
- if data is not None:\r
- self.update(data)\r
- return self._finish()\r
- \r
- def _finish(self):\r
+ def finish(self):\r
if self.cipher_finalized :\r
raise CipherError, "Cipher operation is already completed"\r
- self.cipher_out = create_string_buffer(len(self.data) + 32)\r
- 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
- if result == 0:\r
- self._clean_ctx()\r
- raise CipherError, "Unable to update cipher"\r
+ outbuf=create_string_buffer(self.block_size)\r
self.cipher_finalized = True\r
- update_data = self.cipher_out.raw[:self.cipher_out_len.value]\r
- result = self.libcrypto.EVP_CipherFinal_ex(self.ctx, byref(self.cipher_out), byref(self.cipher_out_len))\r
+ result = self.libcrypto.EVP_CipherFinal_ex(self.ctx,outbuf , byref(outlen))\r
if result == 0:\r
self._clean_ctx()\r
raise CipherError, "Unable to finalize cipher"\r
- final_data = self.cipher_out.raw[:self.cipher_out_len.value]\r
- return update_data + final_data\r
+ if outlen>0:\r
+ return outbuf.raw[:outlen]\r
+ else\r
+ return ""\r
\r
def _clean_ctx(self):\r
try:\r
del(self.ctx)\r
except AttributeError:\r
pass\r
- self.cipher_out = None\r
- self.cipher_out_len = c_long(0)\r
- self.data = ""\r
- self.cipher_finalized = False
\ No newline at end of file
+ self.cipher_finalized = True\r