|
| 1 | +import os |
| 2 | + |
| 3 | +from ctypes import * |
| 4 | +from rsa import load_crypto_lib, SSLError |
| 5 | + |
| 6 | +_eay = load_crypto_lib() |
| 7 | + |
| 8 | +c_int_p = POINTER(c_int) |
| 9 | + |
| 10 | +# void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); |
| 11 | +EVP_CIPHER_CTX_init = _eay.EVP_CIPHER_CTX_init |
| 12 | +EVP_CIPHER_CTX_init.argtypes = [c_void_p] |
| 13 | +EVP_CIPHER_CTX_init.restype = None |
| 14 | + |
| 15 | +#int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, |
| 16 | +# int *outl, unsigned char *in, int inl); |
| 17 | +EVP_CipherUpdate = _eay.EVP_CipherUpdate |
| 18 | +EVP_CipherUpdate.argtypes = [c_void_p, c_char_p, c_int_p, c_char_p, c_int] |
| 19 | +EVP_CipherUpdate.restype = c_int |
| 20 | + |
| 21 | +#int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, |
| 22 | +# int *outl); |
| 23 | +EVP_CipherFinal = _eay.EVP_CipherFinal |
| 24 | +EVP_CipherFinal.argtypes = [c_void_p, c_char_p, c_int_p] |
| 25 | +EVP_CipherFinal.restype = c_int |
| 26 | + |
| 27 | +#EVP_CIPHER *EVP_aes_256_cbc(void); |
| 28 | +EVP_aes_256_cbc = _eay.EVP_aes_256_cbc |
| 29 | +EVP_aes_256_cbc.argtypes = [] |
| 30 | +EVP_aes_256_cbc.restype = c_void_p |
| 31 | + |
| 32 | +#EVP_MD *EVP_sha1(void); |
| 33 | +EVP_sha1 = _eay.EVP_sha1 |
| 34 | +EVP_sha1.argtypes = [] |
| 35 | +EVP_sha1.restype = c_void_p |
| 36 | + |
| 37 | +#int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, |
| 38 | +# unsigned char *key, unsigned char *iv, int enc); |
| 39 | +EVP_CipherInit = _eay.EVP_CipherInit |
| 40 | +EVP_CipherInit.argtypes = [c_void_p, c_void_p, c_char_p, c_char_p, c_int] |
| 41 | +EVP_CipherInit.restype = c_int |
| 42 | + |
| 43 | +#int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding); |
| 44 | +EVP_CIPHER_CTX_set_padding = _eay.EVP_CIPHER_CTX_set_padding |
| 45 | +EVP_CIPHER_CTX_set_padding.argtypes = [c_void_p, c_int] |
| 46 | +EVP_CIPHER_CTX_set_padding.restype = c_int |
| 47 | + |
| 48 | +# Structures required for ctypes |
| 49 | + |
| 50 | +EVP_MAX_IV_LENGTH = 16 |
| 51 | +EVP_MAX_BLOCK_LENGTH = 32 |
| 52 | +AES_BLOCK_SIZE = 16 |
| 53 | + |
| 54 | +class EVP_CIPHER(Structure): |
| 55 | + _fields_ = [ |
| 56 | + ("nid", c_int), |
| 57 | + ("block_size", c_int), |
| 58 | + ("key_len", c_int), |
| 59 | + ("iv_len", c_int), |
| 60 | + ("flags", c_ulong), |
| 61 | + ("init", c_voidp), |
| 62 | + ("do_cipher", c_voidp), |
| 63 | + ("cleanup", c_voidp), |
| 64 | + ("set_asn1_parameters", c_voidp), |
| 65 | + ("get_asn1_parameters", c_voidp), |
| 66 | + ("ctrl", c_voidp), |
| 67 | + ("app_data", c_voidp) |
| 68 | + ] |
| 69 | + |
| 70 | +class EVP_CIPHER_CTX(Structure): |
| 71 | + _fields_ = [ |
| 72 | + ("cipher", POINTER(EVP_CIPHER)), |
| 73 | + ("engine", c_voidp), |
| 74 | + ("encrypt", c_int), |
| 75 | + ("buflen", c_int), |
| 76 | + ("oiv", c_ubyte * EVP_MAX_IV_LENGTH), |
| 77 | + ("iv", c_ubyte * EVP_MAX_IV_LENGTH), |
| 78 | + ("buf", c_ubyte * EVP_MAX_BLOCK_LENGTH), |
| 79 | + ("num", c_int), |
| 80 | + ("app_data", c_voidp), |
| 81 | + ("key_len", c_int), |
| 82 | + ("flags", c_ulong), |
| 83 | + ("cipher_data", c_voidp), |
| 84 | + ("final_used", c_int), |
| 85 | + ("block_mask", c_int), |
| 86 | + ("final", c_ubyte * EVP_MAX_BLOCK_LENGTH) ] |
| 87 | + |
| 88 | + |
| 89 | +class AES256Cipher(object): |
| 90 | + def __init__(self, key, iv, salt='12345678'): |
| 91 | + self.key_data = create_string_buffer(key) |
| 92 | + self.iv = create_string_buffer(iv) |
| 93 | + self.encryptor = self.decryptor = None |
| 94 | + self.salt = create_string_buffer(salt) |
| 95 | + |
| 96 | + self.encryptor = EVP_CIPHER_CTX() |
| 97 | + self._init_cipher(byref(self.encryptor), 1) |
| 98 | + |
| 99 | + self.decryptor = EVP_CIPHER_CTX() |
| 100 | + self._init_cipher(byref(self.decryptor), 0) |
| 101 | + |
| 102 | + def _init_cipher(self, ctypes_cipher, crypt_mode): |
| 103 | + """ crypt_mode parameter is a flag deciding whether the cipher should be |
| 104 | + used for encryption (1) or decryption (0) """ |
| 105 | + EVP_CIPHER_CTX_init(ctypes_cipher) |
| 106 | + EVP_CipherInit(ctypes_cipher, EVP_aes_256_cbc(), self.key_data, self.iv, c_int(crypt_mode)) |
| 107 | + EVP_CIPHER_CTX_set_padding(ctypes_cipher, c_int(1)) |
| 108 | + |
| 109 | + def _process_data(self, ctypes_cipher, data): |
| 110 | + length = c_int(len(data)) |
| 111 | + buf_length = c_int(length.value + AES_BLOCK_SIZE) |
| 112 | + buf = create_string_buffer(buf_length.value) |
| 113 | + |
| 114 | + final_buf = create_string_buffer(AES_BLOCK_SIZE) |
| 115 | + final_length = c_int(0) |
| 116 | + |
| 117 | + EVP_CipherUpdate(ctypes_cipher, buf, byref(buf_length), create_string_buffer(data), length) |
| 118 | + EVP_CipherFinal(ctypes_cipher, final_buf, byref(final_length)) |
| 119 | + |
| 120 | + return string_at(buf, buf_length) + string_at(final_buf, final_length) |
| 121 | + |
| 122 | + |
| 123 | + def encrypt(self, data): |
| 124 | + return self._process_data(byref(self.encryptor), data) |
| 125 | + |
| 126 | + def decrypt(self, data): |
| 127 | + return self._process_data(byref(self.decryptor), data) |
0 commit comments