pyelliptic-1.5.7/0000755000175000017500000000000012571000723013633 5ustar yannyann00000000000000pyelliptic-1.5.7/pyelliptic/0000755000175000017500000000000012571000723016011 5ustar yannyann00000000000000pyelliptic-1.5.7/pyelliptic/openssl.py0000644000175000017500000005021212570777362020071 0ustar yannyann00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2014 Yann GUIBET . # All rights reserved. # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import sys import ctypes import ctypes.util OpenSSL = None class CipherName: def __init__(self, name, pointer, blocksize): self._name = name self._pointer = pointer self._blocksize = blocksize def __str__(self): return ("Cipher : %s | Blocksize : %s | Fonction pointer : %s" % (self._name, str(self._blocksize), str(self._pointer))) def get_pointer(self): return self._pointer() def get_name(self): return self._name def get_blocksize(self): return self._blocksize class _OpenSSL: """ Wrapper for OpenSSL using ctypes """ def __init__(self, library): """ Build the wrapper """ self._lib = ctypes.CDLL(library) self.pointer = ctypes.pointer self.c_int = ctypes.c_int self.byref = ctypes.byref self.create_string_buffer = ctypes.create_string_buffer self.ERR_error_string = self._lib.ERR_error_string self.ERR_error_string.restype = ctypes.c_char_p self.ERR_error_string.argtypes = [ctypes.c_ulong, ctypes.c_char_p] self.ERR_get_error = self._lib.ERR_get_error self.ERR_get_error.restype = ctypes.c_ulong self.ERR_get_error.argtypes = [] self.BN_new = self._lib.BN_new self.BN_new.restype = ctypes.c_void_p self.BN_new.argtypes = [] self.BN_free = self._lib.BN_free self.BN_free.restype = None self.BN_free.argtypes = [ctypes.c_void_p] self.BN_num_bits = self._lib.BN_num_bits self.BN_num_bits.restype = ctypes.c_int self.BN_num_bits.argtypes = [ctypes.c_void_p] self.BN_bn2bin = self._lib.BN_bn2bin self.BN_bn2bin.restype = ctypes.c_int self.BN_bn2bin.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.BN_bin2bn = self._lib.BN_bin2bn self.BN_bin2bn.restype = ctypes.c_void_p self.BN_bin2bn.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p] self.EC_GROUP_get_degree = self._lib.EC_GROUP_get_degree self.EC_GROUP_get_degree.restype = ctypes.c_int self.EC_GROUP_get_degree.argtypes = [ctypes.c_void_p] self.EC_KEY_free = self._lib.EC_KEY_free self.EC_KEY_free.restype = None self.EC_KEY_free.argtypes = [ctypes.c_void_p] self.EC_KEY_new_by_curve_name = self._lib.EC_KEY_new_by_curve_name self.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p self.EC_KEY_new_by_curve_name.argtypes = [ctypes.c_int] self.EC_KEY_generate_key = self._lib.EC_KEY_generate_key self.EC_KEY_generate_key.restype = ctypes.c_int self.EC_KEY_generate_key.argtypes = [ctypes.c_void_p] self.EC_KEY_check_key = self._lib.EC_KEY_check_key self.EC_KEY_check_key.restype = ctypes.c_int self.EC_KEY_check_key.argtypes = [ctypes.c_void_p] self.EC_KEY_get0_private_key = self._lib.EC_KEY_get0_private_key self.EC_KEY_get0_private_key.restype = ctypes.c_void_p self.EC_KEY_get0_private_key.argtypes = [ctypes.c_void_p] self.EC_KEY_get0_public_key = self._lib.EC_KEY_get0_public_key self.EC_KEY_get0_public_key.restype = ctypes.c_void_p self.EC_KEY_get0_public_key.argtypes = [ctypes.c_void_p] self.EC_KEY_get0_group = self._lib.EC_KEY_get0_group self.EC_KEY_get0_group.restype = ctypes.c_void_p self.EC_KEY_get0_group.argtypes = [ctypes.c_void_p] self.EC_POINT_get_affine_coordinates_GFp = self._lib.EC_POINT_get_affine_coordinates_GFp self.EC_POINT_get_affine_coordinates_GFp.restype = ctypes.c_int self.EC_POINT_get_affine_coordinates_GFp.argtypes = 5 * [ctypes.c_void_p] self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key self.EC_KEY_set_private_key.restype = ctypes.c_int self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.EC_KEY_set_public_key = self._lib.EC_KEY_set_public_key self.EC_KEY_set_public_key.restype = ctypes.c_int self.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.EC_KEY_set_group = self._lib.EC_KEY_set_group self.EC_KEY_set_group.restype = ctypes.c_int self.EC_KEY_set_group.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.EC_POINT_set_affine_coordinates_GFp = self._lib.EC_POINT_set_affine_coordinates_GFp self.EC_POINT_set_affine_coordinates_GFp.restype = ctypes.c_int self.EC_POINT_set_affine_coordinates_GFp.argtypes = 5 * [ctypes.c_void_p] self.EC_POINT_new = self._lib.EC_POINT_new self.EC_POINT_new.restype = ctypes.c_void_p self.EC_POINT_new.argtypes = [ctypes.c_void_p] self.EC_POINT_free = self._lib.EC_POINT_free self.EC_POINT_free.restype = None self.EC_POINT_free.argtypes = [ctypes.c_void_p] self.BN_CTX_free = self._lib.BN_CTX_free self.BN_CTX_free.restype = None self.BN_CTX_free.argtypes = [ctypes.c_void_p] self.EC_POINT_mul = self._lib.EC_POINT_mul self.EC_POINT_mul.restype = ctypes.c_int self.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key self.EC_KEY_set_private_key.restype = ctypes.c_int self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.ECDH_OpenSSL = self._lib.ECDH_OpenSSL self._lib.ECDH_OpenSSL.restype = ctypes.c_void_p self._lib.ECDH_OpenSSL.argtypes = [] self.BN_CTX_new = self._lib.BN_CTX_new self._lib.BN_CTX_new.restype = ctypes.c_void_p self._lib.BN_CTX_new.argtypes = [] self.ECDH_set_method = self._lib.ECDH_set_method self._lib.ECDH_set_method.restype = ctypes.c_int self._lib.ECDH_set_method.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.ECDH_compute_key = self._lib.ECDH_compute_key self.ECDH_compute_key.restype = ctypes.c_int self.ECDH_compute_key.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p] self.EVP_CipherInit_ex = self._lib.EVP_CipherInit_ex self.EVP_CipherInit_ex.restype = ctypes.c_int self.EVP_CipherInit_ex.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] self.EVP_CIPHER_CTX_new = self._lib.EVP_CIPHER_CTX_new self.EVP_CIPHER_CTX_new.restype = ctypes.c_void_p self.EVP_CIPHER_CTX_new.argtypes = [] # Cipher self.EVP_aes_128_cfb128 = self._lib.EVP_aes_128_cfb128 self.EVP_aes_128_cfb128.restype = ctypes.c_void_p self.EVP_aes_128_cfb128.argtypes = [] self.EVP_aes_256_cfb128 = self._lib.EVP_aes_256_cfb128 self.EVP_aes_256_cfb128.restype = ctypes.c_void_p self.EVP_aes_256_cfb128.argtypes = [] self.EVP_aes_128_cbc = self._lib.EVP_aes_128_cbc self.EVP_aes_128_cbc.restype = ctypes.c_void_p self.EVP_aes_128_cbc.argtypes = [] self.EVP_aes_256_cbc = self._lib.EVP_aes_256_cbc self.EVP_aes_256_cbc.restype = ctypes.c_void_p self.EVP_aes_256_cbc.argtypes = [] try: self.EVP_aes_128_ctr = self._lib.EVP_aes_128_ctr except AttributeError: pass else: self.EVP_aes_128_ctr.restype = ctypes.c_void_p self.EVP_aes_128_ctr.argtypes = [] try: self.EVP_aes_256_ctr = self._lib.EVP_aes_256_ctr except AttributeError: pass else: self.EVP_aes_256_ctr.restype = ctypes.c_void_p self.EVP_aes_256_ctr.argtypes = [] self.EVP_aes_128_ofb = self._lib.EVP_aes_128_ofb self.EVP_aes_128_ofb.restype = ctypes.c_void_p self.EVP_aes_128_ofb.argtypes = [] self.EVP_aes_256_ofb = self._lib.EVP_aes_256_ofb self.EVP_aes_256_ofb.restype = ctypes.c_void_p self.EVP_aes_256_ofb.argtypes = [] self.EVP_bf_cbc = self._lib.EVP_bf_cbc self.EVP_bf_cbc.restype = ctypes.c_void_p self.EVP_bf_cbc.argtypes = [] self.EVP_bf_cfb64 = self._lib.EVP_bf_cfb64 self.EVP_bf_cfb64.restype = ctypes.c_void_p self.EVP_bf_cfb64.argtypes = [] self.EVP_rc4 = self._lib.EVP_rc4 self.EVP_rc4.restype = ctypes.c_void_p self.EVP_rc4.argtypes = [] self.EVP_CIPHER_CTX_cleanup = self._lib.EVP_CIPHER_CTX_cleanup self.EVP_CIPHER_CTX_cleanup.restype = ctypes.c_int self.EVP_CIPHER_CTX_cleanup.argtypes = [ctypes.c_void_p] self.EVP_CIPHER_CTX_free = self._lib.EVP_CIPHER_CTX_free self.EVP_CIPHER_CTX_free.restype = None self.EVP_CIPHER_CTX_free.argtypes = [ctypes.c_void_p] self.EVP_CipherUpdate = self._lib.EVP_CipherUpdate self.EVP_CipherUpdate.restype = ctypes.c_int self.EVP_CipherUpdate.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int] self.EVP_CipherFinal_ex = self._lib.EVP_CipherFinal_ex self.EVP_CipherFinal_ex.restype = ctypes.c_int self.EVP_CipherFinal_ex.argtypes = 3 * [ctypes.c_void_p] self.EVP_DigestInit = self._lib.EVP_DigestInit self.EVP_DigestInit.restype = ctypes.c_int self._lib.EVP_DigestInit.argtypes = 2 * [ctypes.c_void_p] self.EVP_DigestInit_ex = self._lib.EVP_DigestInit_ex self.EVP_DigestInit_ex.restype = ctypes.c_int self._lib.EVP_DigestInit_ex.argtypes = 3 * [ctypes.c_void_p] self.EVP_DigestUpdate = self._lib.EVP_DigestUpdate self.EVP_DigestUpdate.restype = ctypes.c_int self.EVP_DigestUpdate.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int] self.EVP_DigestFinal = self._lib.EVP_DigestFinal self.EVP_DigestFinal.restype = ctypes.c_int self.EVP_DigestFinal.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] self.EVP_DigestFinal_ex = self._lib.EVP_DigestFinal_ex self.EVP_DigestFinal_ex.restype = ctypes.c_int self.EVP_DigestFinal_ex.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] self.EVP_ecdsa = self._lib.EVP_ecdsa self._lib.EVP_ecdsa.restype = ctypes.c_void_p self._lib.EVP_ecdsa.argtypes = [] self.ECDSA_sign = self._lib.ECDSA_sign self.ECDSA_sign.restype = ctypes.c_int self.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] self.ECDSA_verify = self._lib.ECDSA_verify self.ECDSA_verify.restype = ctypes.c_int self.ECDSA_verify.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p] self.EVP_MD_CTX_create = self._lib.EVP_MD_CTX_create self.EVP_MD_CTX_create.restype = ctypes.c_void_p self.EVP_MD_CTX_create.argtypes = [] self.EVP_MD_CTX_init = self._lib.EVP_MD_CTX_init self.EVP_MD_CTX_init.restype = None self.EVP_MD_CTX_init.argtypes = [ctypes.c_void_p] self.EVP_MD_CTX_destroy = self._lib.EVP_MD_CTX_destroy self.EVP_MD_CTX_destroy.restype = None self.EVP_MD_CTX_destroy.argtypes = [ctypes.c_void_p] self.RAND_bytes = self._lib.RAND_bytes self.RAND_bytes.restype = ctypes.c_int self.RAND_bytes.argtypes = [ctypes.c_void_p, ctypes.c_int] self.EVP_sha256 = self._lib.EVP_sha256 self.EVP_sha256.restype = ctypes.c_void_p self.EVP_sha256.argtypes = [] self.i2o_ECPublicKey = self._lib.i2o_ECPublicKey self.i2o_ECPublicKey.restype = ctypes.c_int self.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.EVP_sha512 = self._lib.EVP_sha512 self.EVP_sha512.restype = ctypes.c_void_p self.EVP_sha512.argtypes = [] self.HMAC = self._lib.HMAC self.HMAC.restype = ctypes.c_void_p self.HMAC.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p] try: self.PKCS5_PBKDF2_HMAC = self._lib.PKCS5_PBKDF2_HMAC except: # The above is not compatible with all versions of OSX. self.PKCS5_PBKDF2_HMAC = self._lib.PKCS5_PBKDF2_HMAC_SHA1 self.PKCS5_PBKDF2_HMAC.restype = ctypes.c_int self.PKCS5_PBKDF2_HMAC.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p] self._set_ciphers() self._set_curves() def _set_ciphers(self): self.cipher_algo = { 'aes-128-cbc': CipherName('aes-128-cbc', self.EVP_aes_128_cbc, 16), 'aes-256-cbc': CipherName('aes-256-cbc', self.EVP_aes_256_cbc, 16), 'aes-128-cfb': CipherName('aes-128-cfb', self.EVP_aes_128_cfb128, 16), 'aes-256-cfb': CipherName('aes-256-cfb', self.EVP_aes_256_cfb128, 16), 'aes-128-ofb': CipherName('aes-128-ofb', self._lib.EVP_aes_128_ofb, 16), 'aes-256-ofb': CipherName('aes-256-ofb', self._lib.EVP_aes_256_ofb, 16), # 'aes-128-ctr': CipherName('aes-128-ctr', # self._lib.EVP_aes_128_ctr, # 16), # 'aes-256-ctr': CipherName('aes-256-ctr', # self._lib.EVP_aes_256_ctr, # 16), 'bf-cfb': CipherName('bf-cfb', self.EVP_bf_cfb64, 8), 'bf-cbc': CipherName('bf-cbc', self.EVP_bf_cbc, 8), 'rc4': CipherName('rc4', self.EVP_rc4, # 128 is the initialisation size not block size 128), } if hasattr(self, 'EVP_aes_128_ctr'): self.cipher_algo['aes-128-ctr'] = CipherName( 'aes-128-ctr', self._lib.EVP_aes_128_ctr, 16 ) if hasattr(self, 'EVP_aes_256_ctr'): self.cipher_algo['aes-256-ctr'] = CipherName( 'aes-256-ctr', self._lib.EVP_aes_256_ctr, 16 ) def _set_curves(self): self.curves = { 'secp112r1': 704, 'secp112r2': 705, 'secp128r1': 706, 'secp128r2': 707, 'secp160k1': 708, 'secp160r1': 709, 'secp160r2': 710, 'secp192k1': 711, 'secp224k1': 712, 'secp224r1': 713, 'secp256k1': 714, 'secp384r1': 715, 'secp521r1': 716, 'sect113r1': 717, 'sect113r2': 718, 'sect131r1': 719, 'sect131r2': 720, 'sect163k1': 721, 'sect163r1': 722, 'sect163r2': 723, 'sect193r1': 724, 'sect193r2': 725, 'sect233k1': 726, 'sect233r1': 727, 'sect239k1': 728, 'sect283k1': 729, 'sect283r1': 730, 'sect409k1': 731, 'sect409r1': 732, 'sect571k1': 733, 'sect571r1': 734, 'prime256v1': 415, } def BN_num_bytes(self, x): """ returns the length of a BN (OpenSSl API) """ return int((self.BN_num_bits(x) + 7) / 8) def get_cipher(self, name): """ returns the OpenSSL cipher instance """ if name not in self.cipher_algo: raise Exception("Unknown cipher") return self.cipher_algo[name] def get_curve(self, name): """ returns the id of a elliptic curve """ if name not in self.curves: raise Exception("Unknown curve") return self.curves[name] def get_curve_by_id(self, id): """ returns the name of a elliptic curve with his id """ res = None for i in self.curves: if self.curves[i] == id: res = i break if res is None: raise Exception("Unknown curve") return res def rand(self, size): """ OpenSSL random function """ buffer = self.malloc(0, size) if self.RAND_bytes(buffer, size) != 1: raise RuntimeError("OpenSSL RAND_bytes failed") return buffer.raw def malloc(self, data, size): """ returns a create_string_buffer (ctypes) """ buffer = None if data != 0: if sys.version_info.major == 3 and isinstance(data, type('')): data = data.encode() buffer = self.create_string_buffer(data, size) else: buffer = self.create_string_buffer(size) return buffer def get_error(self): return OpenSSL.ERR_error_string(OpenSSL.ERR_get_error(), None) libname = ctypes.util.find_library('crypto') if libname is None: # For Windows ... libname = ctypes.util.find_library('libeay32.dll') if libname is None: raise Exception("Couldn't load OpenSSL lib ...") OpenSSL = _OpenSSL(libname) pyelliptic-1.5.7/pyelliptic/ecc.py0000644000175000017500000005240012570777362017141 0ustar yannyann00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2014 Yann GUIBET . # All rights reserved. # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from hashlib import sha512 from binascii import hexlify, unhexlify from .openssl import OpenSSL from .cipher import Cipher from .hash import hmac_sha256, equals from struct import pack, unpack class ECC: """ Asymmetric encryption with Elliptic Curve Cryptography (ECC) ECDH, ECDSA and ECIES import pyelliptic alice = pyelliptic.ECC() # default curve: sect283r1 bob = pyelliptic.ECC(curve='sect571r1') ciphertext = alice.encrypt("Hello Bob", bob.get_pubkey()) print bob.decrypt(ciphertext) signature = bob.sign("Hello Alice") # alice's job : print pyelliptic.ECC( pubkey=bob.get_pubkey()).verify(signature, "Hello Alice") # ERROR !!! try: key = alice.get_ecdh_key(bob.get_pubkey()) except: print("For ECDH key agreement,\ the keys must be defined on the same curve !") alice = pyelliptic.ECC(curve='sect571r1') print alice.get_ecdh_key(bob.get_pubkey()).encode('hex') print bob.get_ecdh_key(alice.get_pubkey()).encode('hex') """ def __init__(self, pubkey=None, privkey=None, pubkey_x=None, pubkey_y=None, raw_privkey=None, curve='sect283r1'): """ For a normal and High level use, specifie pubkey, privkey (if you need) and the curve """ if type(curve) == str: self.curve = OpenSSL.get_curve(curve) else: self.curve = curve if pubkey_x is not None and pubkey_y is not None: self._set_keys(pubkey_x, pubkey_y, raw_privkey) elif pubkey is not None: pubkey_x, pubkey_y = ECC._decode_pubkey(pubkey) if privkey is not None: raw_privkey = ECC._decode_privkey(privkey) self._set_keys(pubkey_x, pubkey_y, raw_privkey) else: self.privkey, self.pubkey_x, self.pubkey_y = self._generate() def _set_keys(self, pubkey_x, pubkey_y, privkey): if self.raw_check_key(privkey, pubkey_x, pubkey_y) < 0: self.pubkey_x = None self.pubkey_y = None self.privkey = None raise Exception("Bad ECC keys ...") else: self.pubkey_x = pubkey_x self.pubkey_y = pubkey_y self.privkey = privkey @staticmethod def get_curves(): """ static method, returns the list of all the curves available """ return OpenSSL.curves.keys() def get_curve(self): return OpenSSL.get_curve_by_id(self.curve) def get_curve_id(self): return self.curve def get_pubkey(self, _format='binary'): """ High level function which returns : pubkeyX + pubkeyY """ binary = b''.join(( self.pubkey_x, self.pubkey_y )) if _format is 'binary': pubkey = b'' + unhexlify('04') + binary elif _format is 'hex': pubkey = b'04' + binary.encode('hex') else: raise Exception("[ECC] Unsupported pubkey output format ...") return pubkey def get_privkey(self): """ High level function which returns privkey """ return self.privkey @staticmethod def _decode_pubkey(pubkey, format='binary'): if format is 'binary': binary_key = pubkey elif format is 'hex': binary_key = unhexlify(pubkey) else: raise Exception("[ECC] Unsupported pubkey input format") conv_form = binary_key[0:1] if hexlify(conv_form) != b'04': raise Exception("[ECC] Unsupported pubkey point conversion form") i = int(len(binary_key) / 2 + 1) pubkey_x = binary_key[1:i] pubkey_y = binary_key[i:] return pubkey_x, pubkey_y @staticmethod def _decode_privkey(privkey): return privkey def _old_get_pubkey(self): """ Old get_pubkey, keeps for compatibility issues. """ return b''.join((pack('!H', self.curve), pack('!H', len(self.pubkey_x)), self.pubkey_x, pack('!H', len(self.pubkey_y)), self.pubkey_y )) def _old_get_privkey(self): """ Old get_privkey, keeps for compatibility issues. """ return b''.join((pack('!H', self.curve), pack('!H', len(self.privkey)), self.privkey )) @staticmethod def _old_decode_pubkey(pubkey): """ Converts old exported pubkey to new format """ i = 0 curve = unpack('!H', pubkey[i:i + 2])[0] i += 2 tmplen = unpack('!H', pubkey[i:i + 2])[0] i += 2 pubkey_x = pubkey[i:i + tmplen] i += tmplen tmplen = unpack('!H', pubkey[i:i + 2])[0] i += 2 pubkey_y = pubkey[i:i + tmplen] i += tmplen return curve, pubkey_x, pubkey_y, i @staticmethod def _old_decode_privkey(privkey): """ Converts old exported privkey to new format """ i = 0 curve = unpack('!H', privkey[i:i + 2])[0] i += 2 tmplen = unpack('!H', privkey[i:i + 2])[0] i += 2 privkey = privkey[i:i + tmplen] i += tmplen return curve, privkey, i def _generate(self): try: pub_key_x = OpenSSL.BN_new() pub_key_y = OpenSSL.BN_new() key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_generate_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_generate_key FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error()) priv_key = OpenSSL.EC_KEY_get0_private_key(key) group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_KEY_get0_public_key(key) if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0 )) == 0: raise Exception( "[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error()) field_size = OpenSSL.EC_GROUP_get_degree(OpenSSL.EC_KEY_get0_group(key)) secret_len = int((field_size + 7) / 8) privkey = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(priv_key)) pubkeyx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_x)) pubkeyy = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_y)) OpenSSL.BN_bn2bin(priv_key, privkey) privkey = privkey.raw OpenSSL.BN_bn2bin(pub_key_x, pubkeyx) pubkeyx = pubkeyx.raw OpenSSL.BN_bn2bin(pub_key_y, pubkeyy) pubkeyy = pubkeyy.raw if len(pubkeyx) < secret_len: pubkeyx = pubkeyx.rjust(secret_len, b'\0') if len(pubkeyy) < secret_len: pubkeyy = pubkeyy.rjust(secret_len, b'\0') self.raw_check_key(privkey, pubkeyx, pubkeyy) return privkey, pubkeyx, pubkeyy finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) def get_ecdh_key(self, pubkey, format='binary'): """ High level function. Compute public key with the local private key and returns a shared binary key """ pubkey_x, pubkey_y = ECC._decode_pubkey(pubkey, format) return self.raw_get_ecdh_key(pubkey_x, pubkey_y) def raw_get_ecdh_key(self, pubkey_x, pubkey_y): try: ecdh_keybuffer = OpenSSL.malloc(0, 32) other_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if other_key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error()) other_pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0) other_pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0) other_group = OpenSSL.EC_KEY_get0_group(other_key) other_pub_key = OpenSSL.EC_POINT_new(other_group) if (other_pub_key == None): raise Exception("[OpenSSl] EC_POINT_new FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(other_group, other_pub_key, other_pub_key_x, other_pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ..." + OpenSSL.get_error()) if (OpenSSL.EC_KEY_set_public_key(other_key, other_pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_check_key(other_key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error()) own_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if own_key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error()) own_priv_key = OpenSSL.BN_bin2bn( self.privkey, len(self.privkey), 0) if (OpenSSL.EC_KEY_set_private_key(own_key, own_priv_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ... " + OpenSSL.get_error()) OpenSSL.ECDH_set_method(own_key, OpenSSL.ECDH_OpenSSL()) ecdh_keylen = OpenSSL.ECDH_compute_key( ecdh_keybuffer, 32, other_pub_key, own_key, 0) if ecdh_keylen != 32: raise Exception("[OpenSSL] ECDH keylen FAIL ... " + OpenSSL.get_error()) return ecdh_keybuffer.raw finally: OpenSSL.EC_KEY_free(other_key) OpenSSL.BN_free(other_pub_key_x) OpenSSL.BN_free(other_pub_key_y) OpenSSL.EC_POINT_free(other_pub_key) OpenSSL.EC_KEY_free(own_key) OpenSSL.BN_free(own_priv_key) def check_key(self, privkey, pubkey): """ Check the public key and the private key. The private key is optional (replace by None) """ pubkey_x, pubkey_y = ECC._decode_pubkey(pubkey) if privkey is None: raw_privkey = None else: raw_privkey = ECC._decode_privkey(privkey) return self.raw_check_key(raw_privkey, pubkey_x, pubkey_y) def raw_check_key(self, privkey, pubkey_x, pubkey_y): curve = self.curve try: key = OpenSSL.EC_KEY_new_by_curve_name(curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error()) if privkey is not None: priv_key = OpenSSL.BN_bin2bn(privkey, len(privkey), 0) pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0) if privkey is not None: if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0: raise Exception( "[OpenSSL] EC_KEY_set_private_key FAIL ... " + OpenSSL.get_error()) group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error()) return 0 finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.EC_POINT_free(pub_key) if privkey is not None: OpenSSL.BN_free(priv_key) def sign(self, inputb): """ Sign the input with ECDSA method and returns the signature """ try: size = len(inputb) buff = OpenSSL.malloc(inputb, size) digest = OpenSSL.malloc(0, 64) md_ctx = OpenSSL.EVP_MD_CTX_create() dgst_len = OpenSSL.pointer(OpenSSL.c_int(0)) siglen = OpenSSL.pointer(OpenSSL.c_int(0)) sig = OpenSSL.malloc(0, 151) key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error()) priv_key = OpenSSL.BN_bin2bn(self.privkey, len(self.privkey), 0) pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0) if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ... " + OpenSSL.get_error()) group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error()) OpenSSL.EVP_MD_CTX_init(md_ctx) OpenSSL.EVP_DigestInit_ex(md_ctx, OpenSSL.EVP_sha256(), None) if (OpenSSL.EVP_DigestUpdate(md_ctx, buff, size)) == 0: raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ... " + OpenSSL.get_error()) OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len) OpenSSL.ECDSA_sign(0, digest, dgst_len.contents, sig, siglen, key) if (OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, sig, siglen.contents, key)) != 1: raise Exception("[OpenSSL] ECDSA_verify FAIL ... " + OpenSSL.get_error()) return sig.raw[0:siglen.contents.value] finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.BN_free(priv_key) OpenSSL.EC_POINT_free(pub_key) OpenSSL.EVP_MD_CTX_destroy(md_ctx) def verify(self, sig, inputb): """ Verify the signature with the input and the local public key. Returns a boolean """ try: bsig = OpenSSL.malloc(sig, len(sig)) binputb = OpenSSL.malloc(inputb, len(inputb)) digest = OpenSSL.malloc(0, 64) dgst_len = OpenSSL.pointer(OpenSSL.c_int(0)) md_ctx = OpenSSL.EVP_MD_CTX_create() key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error()) pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0) group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ... " + OpenSSL.get_error()) if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error()) OpenSSL.EVP_MD_CTX_init(md_ctx) OpenSSL.EVP_DigestInit_ex(md_ctx, OpenSSL.EVP_sha256(), None) if (OpenSSL.EVP_DigestUpdate(md_ctx, binputb, len(inputb))) == 0: raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ... " + OpenSSL.get_error()) OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len) ret = OpenSSL.ECDSA_verify( 0, digest, dgst_len.contents, bsig, len(sig), key) if ret == -1: return False # Fail to Check else: if ret == 0: return False # Bad signature ! else: return True # Good return False finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.EC_POINT_free(pub_key) OpenSSL.EVP_MD_CTX_destroy(md_ctx) def encrypt(self, data, pubkey, ephemcurve=None, ciphername='aes-256-cbc'): """ Encrypt data with ECIES method using the public key of the recipient. """ curve = OpenSSL.get_curve_by_id(self.curve) pubkey_x, pubkey_y = ECC._decode_pubkey(pubkey) return ECC.raw_encrypt(data, pubkey_x, pubkey_y, curve=curve, ephemcurve=ephemcurve, ciphername=ciphername) @staticmethod def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1', ephemcurve=None, ciphername='aes-256-cbc'): if ephemcurve is None: ephemcurve = curve ephem = ECC(curve=ephemcurve) key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] pubkey = ephem.get_pubkey() iv = Cipher.gen_IV(ciphername) ctx = Cipher(key_e, iv, 1, ciphername) ciphertext = iv + pubkey + ctx.ciphering(data) mac = hmac_sha256(key_m, ciphertext) return ciphertext + mac def decrypt(self, data, ciphername='aes-256-cbc'): """ Decrypt data with ECIES method using the local private key """ blocksize = OpenSSL.get_cipher(ciphername).get_blocksize() iv = data[:blocksize] i = blocksize coord_len = len(self.pubkey_x) * 2 + 1 pubkey_x, pubkey_y = ECC._decode_pubkey(data[i:i + coord_len]) i += coord_len ciphertext = data[i:len(data) - 32] i = len(data) - 32 mac = data[i:] key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] if not equals(hmac_sha256(key_m, data[:i]), mac): raise RuntimeError("Fail to verify data") ctx = Cipher(key_e, iv, 0, ciphername) return ctx.ciphering(ciphertext) pyelliptic-1.5.7/pyelliptic/cipher.py0000644000175000017500000000757012554471063017660 0ustar yannyann00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2014 Yann GUIBET . # All rights reserved. # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from .openssl import OpenSSL class Cipher: """ Symmetric encryption import pyelliptic iv = pyelliptic.Cipher.gen_IV('aes-256-cfb') ctx = pyelliptic.Cipher("secretkey", iv, 1, ciphername='aes-256-cfb') ciphertext = ctx.update('test1') ciphertext += ctx.update('test2') ciphertext += ctx.final() ctx2 = pyelliptic.Cipher("secretkey", iv, 0, ciphername='aes-256-cfb') print ctx2.ciphering(ciphertext) """ def __init__(self, key, iv, do, ciphername='aes-256-cbc'): """ do == 1 => Encrypt; do == 0 => Decrypt """ self.cipher = OpenSSL.get_cipher(ciphername) self.ctx = OpenSSL.EVP_CIPHER_CTX_new() if do == 1 or do == 0: k = OpenSSL.malloc(key, len(key)) IV = OpenSSL.malloc(iv, len(iv)) OpenSSL.EVP_CipherInit_ex( self.ctx, self.cipher.get_pointer(), 0, k, IV, do) else: raise Exception("RTFM ...") @staticmethod def get_all_cipher(): """ static method, returns all ciphers available """ return OpenSSL.cipher_algo.keys() @staticmethod def get_blocksize(ciphername): cipher = OpenSSL.get_cipher(ciphername) return cipher.get_blocksize() @staticmethod def gen_IV(ciphername): cipher = OpenSSL.get_cipher(ciphername) return OpenSSL.rand(cipher.get_blocksize()) def update(self, input): i = OpenSSL.c_int(0) buffer = OpenSSL.malloc(b"", len(input) + self.cipher.get_blocksize()) inp = OpenSSL.malloc(input, len(input)) if OpenSSL.EVP_CipherUpdate(self.ctx, OpenSSL.byref(buffer), OpenSSL.byref(i), inp, len(input)) == 0: raise Exception("[OpenSSL] EVP_CipherUpdate FAIL ...") return buffer.raw[0:i.value] def final(self): i = OpenSSL.c_int(0) buffer = OpenSSL.malloc(b"", self.cipher.get_blocksize()) if (OpenSSL.EVP_CipherFinal_ex(self.ctx, OpenSSL.byref(buffer), OpenSSL.byref(i))) == 0: raise Exception("[OpenSSL] EVP_CipherFinal_ex FAIL ...") return buffer.raw[0:i.value] def ciphering(self, input): """ Do update and final in one method """ buff = self.update(input) return buff + self.final() def __del__(self): OpenSSL.EVP_CIPHER_CTX_cleanup(self.ctx) OpenSSL.EVP_CIPHER_CTX_free(self.ctx) pyelliptic-1.5.7/pyelliptic/hash.py0000644000175000017500000000573212554471063017327 0ustar yannyann00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2014 Yann GUIBET . # All rights reserved. # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from .openssl import OpenSSL # For python3 def _equals_bytes(a, b): if len(a) != len(b): return False result = 0 for x, y in zip(a, b): result |= x ^ y return result == 0 def _equals_str(a, b): if len(a) != len(b): return False result = 0 for x, y in zip(a, b): result |= ord(x) ^ ord(y) return result == 0 def equals(a, b): if isinstance(a, str): return _equals_str(a, b) else: return _equals_bytes(a, b) def hmac_sha256(k, m): """ Compute the key and the message with HMAC SHA5256 """ key = OpenSSL.malloc(k, len(k)) d = OpenSSL.malloc(m, len(m)) md = OpenSSL.malloc(0, 32) i = OpenSSL.pointer(OpenSSL.c_int(0)) OpenSSL.HMAC(OpenSSL.EVP_sha256(), key, len(k), d, len(m), md, i) return md.raw def hmac_sha512(k, m): """ Compute the key and the message with HMAC SHA512 """ key = OpenSSL.malloc(k, len(k)) d = OpenSSL.malloc(m, len(m)) md = OpenSSL.malloc(0, 64) i = OpenSSL.pointer(OpenSSL.c_int(0)) OpenSSL.HMAC(OpenSSL.EVP_sha512(), key, len(k), d, len(m), md, i) return md.raw def pbkdf2(password, salt=None, i=10000, keylen=64): if salt is None: salt = OpenSSL.rand(8) p_password = OpenSSL.malloc(password, len(password)) p_salt = OpenSSL.malloc(salt, len(salt)) output = OpenSSL.malloc(0, keylen) OpenSSL.PKCS5_PBKDF2_HMAC(p_password, len(password), p_salt, len(p_salt), i, OpenSSL.EVP_sha256(), keylen, output) return salt, output.raw pyelliptic-1.5.7/pyelliptic/__init__.py0000644000175000017500000000321212570777362020143 0ustar yannyann00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2014 # Author: Yann GUIBET # Contact: # All rights reserved. # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. __version__ = '1.5.7' __all__ = [ 'OpenSSL', 'ecc', 'cipher', 'hash', ] from .openssl import OpenSSL from .ecc import ECC from .cipher import Cipher from .hash import hmac_sha256, hmac_sha512, pbkdf2, equals pyelliptic-1.5.7/pyelliptic/arithmetic.py0000644000175000017500000001125212554471063020527 0ustar yannyann00000000000000# Copyright (c) 2012-2014 Jonathan Warren # Copyright (c) 2013-2014 The Bitmessage Developers # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import re import hashlib P = 2**256-2**32-2**9-2**8-2**7-2**6-2**4-1 A = 0 Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240 Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424 G = (Gx, Gy) def inv(a, n): lm, hm = 1, 0 low, high = a % n, n while low > 1: r = high / low nm, new = hm - lm * r, high - low * r lm, low, hm, high = nm, new, lm, low return lm % n def get_code_string(base): if base == 2: return '01' elif base == 10: return '0123456789' elif base == 16: return "0123456789abcdef" elif base == 58: return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" elif base == 256: return ''.join([chr(x) for x in range(256)]) else: raise ValueError("Invalid base!") def encode(val, base, minlen=0): code_string = get_code_string(base) result = "" while val > 0: result = code_string[val % base] + result val /= base if len(result) < minlen: result = code_string[0] * (minlen - len(result)) + result return result def decode(string, base): code_string = get_code_string(base) result = 0 if base == 16: string = string.lower() while len(string) > 0: result *= base result += code_string.find(string[0]) string = string[1:] return result def changebase(string, frm, to, minlen=0): return encode(decode(string, frm), to, minlen) def base10_add(a, b): if a is None: return b[0], b[1] if b is None: return a[0], a[1] if a[0] == b[0]: if a[1] == b[1]: return base10_double(a[0], a[1]) else: return None m = ((b[1] - a[1]) * inv(b[0] - a[0], P)) % P x = (m * m - a[0] - b[0]) % P y = (m * (a[0] - x) - a[1]) % P return (x, y) def base10_double(a): if a is None: return None m = ((3 * a[0] * a[0] + A) * inv(2 * a[1], P)) % P x = (m * m - 2 * a[0]) % P y = (m * (a[0] - x) - a[1]) % P return (x, y) def base10_multiply(a, n): if n == 0: return G if n == 1: return a if (n % 2) == 0: return base10_double(base10_multiply(a, n / 2)) if (n % 2) == 1: return base10_add(base10_double(base10_multiply(a, n / 2)), a) def hex_to_point(h): return (decode(h[2:66], 16), decode(h[66:], 16)) def point_to_hex(p): return '04' + encode(p[0], 16, 64) + encode(p[1], 16, 64) def multiply(privkey, pubkey): return point_to_hex(base10_multiply(hex_to_point(pubkey), decode(privkey, 16))) def privtopub(privkey): return point_to_hex(base10_multiply(G, decode(privkey, 16))) def add(p1, p2): if (len(p1) == 32): return encode(decode(p1, 16) + decode(p2, 16) % P, 16, 32) else: return point_to_hex(base10_add(hex_to_point(p1), hex_to_point(p2))) def hash_160(string): intermed = hashlib.sha256(string).digest() ripemd160 = hashlib.new('ripemd160') ripemd160.update(intermed) return ripemd160.digest() def dbl_sha256(string): return hashlib.sha256(hashlib.sha256(string).digest()).digest() def bin_to_b58check(inp): inp_fmtd = '\x00' + inp leadingzbytes = len(re.match('^\x00*', inp_fmtd).group(0)) checksum = dbl_sha256(inp_fmtd)[:4] return '1' * leadingzbytes + changebase(inp_fmtd + checksum, 256, 58) # Convert a public key (in hex) to a Bitcoin address def pubkey_to_address(pubkey): return bin_to_b58check(hash_160(changebase(pubkey, 16, 256))) pyelliptic-1.5.7/setup.cfg0000644000175000017500000000007312571000723015454 0ustar yannyann00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 pyelliptic-1.5.7/setup.py0000644000175000017500000000413112570777362015367 0ustar yannyann00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2014 Yann GUIBET . # All rights reserved. # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from setuptools import setup, find_packages setup( name="pyelliptic", version='1.5.7', url='https://github.com/yann2192/pyelliptic', license='BSD', description= "Python OpenSSL wrapper for modern cryptography with " + "ECC, AES, HMAC, Blowfish, ...", author='Yann GUIBET', author_email='yannguibet@gmail.com', packages=find_packages(), classifiers=[ 'Operating System :: Unix', 'Operating System :: Microsoft :: Windows', 'Environment :: MacOS X', 'Programming Language :: Python', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Topic :: Security :: Cryptography', ], ) pyelliptic-1.5.7/PKG-INFO0000644000175000017500000000114612571000723014732 0ustar yannyann00000000000000Metadata-Version: 1.1 Name: pyelliptic Version: 1.5.7 Summary: Python OpenSSL wrapper for modern cryptography with ECC, AES, HMAC, Blowfish, ... Home-page: https://github.com/yann2192/pyelliptic Author: Yann GUIBET Author-email: yannguibet@gmail.com License: BSD Description: UNKNOWN Platform: UNKNOWN Classifier: Operating System :: Unix Classifier: Operating System :: Microsoft :: Windows Classifier: Environment :: MacOS X Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Security :: Cryptography pyelliptic-1.5.7/pyelliptic.egg-info/0000755000175000017500000000000012571000723017503 5ustar yannyann00000000000000pyelliptic-1.5.7/pyelliptic.egg-info/top_level.txt0000644000175000017500000000001312571000714022227 0ustar yannyann00000000000000pyelliptic pyelliptic-1.5.7/pyelliptic.egg-info/dependency_links.txt0000644000175000017500000000000112571000714023551 0ustar yannyann00000000000000 pyelliptic-1.5.7/pyelliptic.egg-info/SOURCES.txt0000644000175000017500000000042012571000714021363 0ustar yannyann00000000000000setup.py pyelliptic/__init__.py pyelliptic/arithmetic.py pyelliptic/cipher.py pyelliptic/ecc.py pyelliptic/hash.py pyelliptic/openssl.py pyelliptic.egg-info/PKG-INFO pyelliptic.egg-info/SOURCES.txt pyelliptic.egg-info/dependency_links.txt pyelliptic.egg-info/top_level.txtpyelliptic-1.5.7/pyelliptic.egg-info/PKG-INFO0000644000175000017500000000114612571000714020602 0ustar yannyann00000000000000Metadata-Version: 1.1 Name: pyelliptic Version: 1.5.7 Summary: Python OpenSSL wrapper for modern cryptography with ECC, AES, HMAC, Blowfish, ... Home-page: https://github.com/yann2192/pyelliptic Author: Yann GUIBET Author-email: yannguibet@gmail.com License: BSD Description: UNKNOWN Platform: UNKNOWN Classifier: Operating System :: Unix Classifier: Operating System :: Microsoft :: Windows Classifier: Environment :: MacOS X Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Security :: Cryptography