| 
					
				 | 
			
			
				@@ -28,8 +28,16 @@ cdef extern from "openssl/evp.h": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                            const unsigned char *key, const unsigned char *iv) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           const unsigned char *key, const unsigned char *iv) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                           int *outl, const unsigned char *in_, int inl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                          int *outl, const unsigned char *in_, int inl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            int *outl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            int *outl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int PKCS5_PBKDF2_HMAC(const char *password, int passwordlen, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                           const unsigned char *salt, int saltlen, int iter, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -85,11 +93,19 @@ cdef class AES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """A thin wrapper around the OpenSSL EVP cipher API 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cdef EVP_CIPHER_CTX ctx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cdef int is_encrypt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def __cinit__(self, key, iv=None): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def __cinit__(self, is_encrypt, key, iv=None): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         EVP_CIPHER_CTX_init(&self.ctx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if not EVP_EncryptInit_ex(&self.ctx, EVP_aes_256_ctr(), NULL, NULL, NULL): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            raise Exception('EVP_EncryptInit_ex failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.is_encrypt = is_encrypt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # Set cipher type and mode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cipher_mode = EVP_aes_256_ctr() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if self.is_encrypt: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not EVP_EncryptInit_ex(&self.ctx, cipher_mode, NULL, NULL, NULL): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception('EVP_EncryptInit_ex failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else:  # decrypt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not EVP_DecryptInit_ex(&self.ctx, cipher_mode, NULL, NULL, NULL): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception('EVP_DecryptInit_ex failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.reset(key, iv) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def __dealloc__(self): 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -102,8 +118,13 @@ cdef class AES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             key2 = key 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if iv: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             iv2 = iv 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if not EVP_EncryptInit_ex(&self.ctx, NULL, NULL, key2, iv2): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            raise Exception('EVP_EncryptInit_ex failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # Initialise key and IV 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if self.is_encrypt: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not EVP_EncryptInit_ex(&self.ctx, NULL, NULL, key2, iv2): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception('EVP_EncryptInit_ex failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else:  # decrypt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not EVP_DecryptInit_ex(&self.ctx, NULL, NULL, key2, iv2): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception('EVP_DecryptInit_ex failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @property 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def iv(self): 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -111,15 +132,37 @@ cdef class AES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def encrypt(self, data): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         cdef int inl = len(data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        cdef int outl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        cdef unsigned char *out = <unsigned char *>malloc(inl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cdef int ctl = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cdef int outl = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # note: modes that use padding, need up to one extra AES block (16b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cdef unsigned char *out = <unsigned char *>malloc(inl+16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if not out: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             raise MemoryError 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if not EVP_EncryptUpdate(&self.ctx, out, &outl, data, inl): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 raise Exception('EVP_EncryptUpdate failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return out[:inl] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ctl = outl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not EVP_EncryptFinal_ex(&self.ctx, out+ctl, &outl): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception('EVP_EncryptFinal failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ctl += outl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return out[:ctl] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         finally: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             free(out) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    decrypt = encrypt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def decrypt(self, data): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cdef int inl = len(data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cdef int ptl = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cdef int outl = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cdef unsigned char *out = <unsigned char *>malloc(inl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if not out: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            raise MemoryError 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not EVP_DecryptUpdate(&self.ctx, out, &outl, data, inl): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception('EVP_DecryptUpdate failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ptl = outl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if EVP_DecryptFinal_ex(&self.ctx, out+outl, &outl) <= 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception('EVP_DecryptFinal failed') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ptl += outl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return out[:ptl] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        finally: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            free(out) 
			 |