| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 | """A thin ctypes based wrapper for OpenSSL 1.0"""import osfrom ctypes import cdll, c_char_p, c_int, c_uint, c_void_p, POINTER, create_string_bufferfrom ctypes.util import find_libraryimport structdef _find_libcrypto():    _possible_paths = [        find_library('crypto'),        os.environ.get('ATTIC_LIBCRYPTO_PATH'),        '/usr/local/opt/openssl/lib/libcrypto.dylib',  # OS X Brew        '/usr/local/lib/libcrypto.so',                 # FreeBSD Ports        '/usr/local/ssl/lib/libcrypto.so'    ]    for path in _possible_paths:        try:            lib = cdll.LoadLibrary(path)            if hasattr(lib, 'PKCS5_PBKDF2_HMAC'):                return lib        except OSError:            pass    raise Exception('Failed to find libcrypto version >= 1.0')libcrypto = _find_libcrypto()libcrypto.PKCS5_PBKDF2_HMAC.argtypes = (c_char_p, c_int, c_char_p, c_int, c_int, c_void_p, c_int, c_char_p)libcrypto.EVP_sha256.restype = c_void_plibcrypto.AES_set_encrypt_key.argtypes = (c_char_p, c_int, c_char_p)libcrypto.AES_ctr128_encrypt.argtypes = (c_char_p, c_char_p, c_int, c_char_p, c_char_p, c_char_p, POINTER(c_uint))libcrypto.RAND_bytes.argtypes = (c_char_p, c_int)libcrypto.RAND_bytes.restype = c_int_int = struct.Struct('>I')_long = struct.Struct('>Q')bytes_to_int = lambda x, offset=0: _int.unpack_from(x, offset)[0]bytes_to_long = lambda x, offset=0: _long.unpack_from(x, offset)[0]long_to_bytes = lambda x: _long.pack(x)def num_aes_blocks(length):    """Return the number of AES blocks required to encrypt/decrypt *length* bytes of data    """    return (length + 15) // 16def pbkdf2_sha256(password, salt, iterations, size):    """Password based key derivation function 2 (RFC2898)    """    key = create_string_buffer(size)    rv = libcrypto.PKCS5_PBKDF2_HMAC(password, len(password), salt, len(salt), iterations, libcrypto.EVP_sha256(), size, key)    if not rv:        raise Exception('PKCS5_PBKDF2_HMAC failed')    return key.rawdef get_random_bytes(n):    """Return n cryptographically strong pseudo-random bytes    """    buf = create_string_buffer(n)    if libcrypto.RAND_bytes(buf, n) < 1:        raise Exception('RAND_bytes failed')    return buf.rawclass AES:    """A thin wrapper around the OpenSSL AES CTR_MODE cipher    """    def __init__(self, key, iv=None):        self.key = create_string_buffer(2000)        self.iv = create_string_buffer(16)        self.buf = create_string_buffer(16)        self.num = c_uint()        self.reset(key, iv)    def reset(self, key=None, iv=None):        if key:            libcrypto.AES_set_encrypt_key(key, len(key) * 8, self.key)        if iv:            self.iv.raw = iv        self.num.value = 0    def encrypt(self, data):        out = create_string_buffer(len(data))        libcrypto.AES_ctr128_encrypt(data, out, len(data), self.key, self.iv, self.buf, self.num)        return out.raw    decrypt = encrypt
 |