From 2e0f7755c609a9209d3ae3c46da9a769e4cf9ea4 Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Mon, 26 Aug 2019 17:46:25 +0200 Subject: [PATCH] Blind signature support in pyelliptic - add blind signature functionality to pyelliptic as described in #1409 - add tests for blind signatures - PEP8 fixes for pyelliptic - some minor refactoring is necessary for further integration, this is just a minimal implementation to pass a test --- src/pyelliptic/__init__.py | 12 +- src/pyelliptic/cipher.py | 2 +- src/pyelliptic/ecc.py | 6 +- src/pyelliptic/eccblind.py | 179 ++++++++++++++++++++++++++++++ src/pyelliptic/hash.py | 2 +- src/pyelliptic/openssl.py | 222 ++++++++++++++++++++++++++++++------- src/tests/test_blindsig.py | 22 ++++ 7 files changed, 394 insertions(+), 51 deletions(-) create mode 100644 src/pyelliptic/eccblind.py create mode 100644 src/tests/test_blindsig.py diff --git a/src/pyelliptic/__init__.py b/src/pyelliptic/__init__.py index 761d08af..1d6a928f 100644 --- a/src/pyelliptic/__init__.py +++ b/src/pyelliptic/__init__.py @@ -2,18 +2,20 @@ # Author: Yann GUIBET # Contact: +from .openssl import OpenSSL +from .ecc import ECC +from .eccblind import ECCBlind +from .cipher import Cipher +from .hash import hmac_sha256, hmac_sha512, pbkdf2 + __version__ = '1.3' __all__ = [ 'OpenSSL', 'ECC', + 'ECCBlind', 'Cipher', 'hmac_sha256', 'hmac_sha512', 'pbkdf2' ] - -from .openssl import OpenSSL -from .ecc import ECC -from .cipher import Cipher -from .hash import hmac_sha256, hmac_sha512, pbkdf2 diff --git a/src/pyelliptic/cipher.py b/src/pyelliptic/cipher.py index b597cafa..bc1af6b0 100644 --- a/src/pyelliptic/cipher.py +++ b/src/pyelliptic/cipher.py @@ -4,7 +4,7 @@ # Copyright (C) 2011 Yann GUIBET # See LICENSE for details. -from pyelliptic.openssl import OpenSSL +from openssl import OpenSSL class Cipher: diff --git a/src/pyelliptic/ecc.py b/src/pyelliptic/ecc.py index fb0d6773..2de0bfe9 100644 --- a/src/pyelliptic/ecc.py +++ b/src/pyelliptic/ecc.py @@ -12,9 +12,9 @@ src/pyelliptic/ecc.py from hashlib import sha512 from struct import pack, unpack -from pyelliptic.cipher import Cipher -from pyelliptic.hash import equals, hmac_sha256 -from pyelliptic.openssl import OpenSSL +from cipher import Cipher +from hash import equals, hmac_sha256 +from openssl import OpenSSL class ECC(object): diff --git a/src/pyelliptic/eccblind.py b/src/pyelliptic/eccblind.py new file mode 100644 index 00000000..f8b43da5 --- /dev/null +++ b/src/pyelliptic/eccblind.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +""" +ECC blind signature functionality based on "An Efficient Blind Signature Scheme +Based on the Elliptic CurveDiscrete Logarithm Problem" by Morteza Nikooghadama + and Ali Zakerolhosseini , +http://www.isecure-journal.com/article_39171_47f9ec605dd3918c2793565ec21fcd7a.pdf +""" + +# variable names are based on the math in the paper, so they don't conform +# to PEP8 +# pylint: disable=invalid-name + +from .openssl import OpenSSL + + +class ECCBlind(object): # pylint: disable=too-many-instance-attributes + """ + Class for ECC blind signature functionality + """ + + # init + k = None + R = None + keypair = None + F = None + Q = None + a = None + b = None + c = None + binv = None + r = None + m = None + m_ = None + s_ = None + signature = None + + @staticmethod + def ec_get_random(group, ctx): + """ + Random point from finite field + """ + order = OpenSSL.BN_new() + OpenSSL.EC_GROUP_get_order(group, order, ctx) + OpenSSL.BN_rand(order, OpenSSL.BN_num_bits(order), 0, 0) + return order + + @staticmethod + def ec_invert(group, a, ctx): + """ + ECC inversion + """ + order = OpenSSL.BN_new() + OpenSSL.EC_GROUP_get_order(group, order, ctx) + inverse = OpenSSL.BN_mod_inverse(0, a, order, ctx) + return inverse + + @staticmethod + def ec_gen_keypair(group, ctx): + """ + Generate an ECC keypair + """ + d = ECCBlind.ec_get_random(group, ctx) + Q = OpenSSL.EC_POINT_new(group) + OpenSSL.EC_POINT_mul(group, Q, d, 0, 0, 0) + return (d, Q) + + def __init__(self, curve="secp256k1"): + self.group = OpenSSL.EC_GROUP_new_by_curve_name(OpenSSL.get_curve(curve)) + self.ctx = OpenSSL.BN_CTX_new() + + # Order n + self.n = OpenSSL.BN_new() + OpenSSL.EC_GROUP_get_order(self.group, self.n, self.ctx) + + # Identity O (infinity) + self.iO = OpenSSL.EC_POINT_new(self.group) + OpenSSL.EC_POINT_set_to_infinity(self.group, self.iO) + + # Generator G + self.G = OpenSSL.EC_GROUP_get0_generator(self.group) + + # Certifier's pubkey + self.pubkey = (self.group, self.G, self.n) + + def signer_init(self): + """ + Init signer + """ + # Signer: Random integer k + self.k = ECCBlind.ec_get_random(self.group, self.ctx) + + # R = kG + self.R = OpenSSL.EC_POINT_new(self.group) + OpenSSL.EC_POINT_mul(self.group, self.R, self.k, 0, 0, 0) + + def create_signing_request(self, msg): + """ + Requester creates a new signing request + """ + # new keypair + self.keypair = ECCBlind.ec_gen_keypair(self.group, self.ctx) + + # Requester: 3 random blinding factors + self.F = OpenSSL.EC_POINT_new(self.group) + OpenSSL.EC_POINT_set_to_infinity(self.group, self.F) + temp = OpenSSL.EC_POINT_new(self.group) + self.Q = self.keypair[1] + abinv = OpenSSL.BN_new() + + # F != O + while OpenSSL.EC_POINT_cmp(self.group, self.F, self.iO, self.ctx) == 0: + self.a = ECCBlind.ec_get_random(self.group, self.ctx) + self.b = ECCBlind.ec_get_random(self.group, self.ctx) + self.c = ECCBlind.ec_get_random(self.group, self.ctx) + + # F = b^-1 * R... + self.binv = ECCBlind.ec_invert(self.group, self.b, self.ctx) + OpenSSL.EC_POINT_mul(self.group, temp, 0, self.R, self.binv, 0) + OpenSSL.EC_POINT_copy(self.F, temp) + + # ... + a*b^-1 * Q... + OpenSSL.BN_mul(abinv, self.a, self.binv, self.ctx) + OpenSSL.EC_POINT_mul(self.group, temp, 0, self.Q, abinv, 0) + OpenSSL.EC_POINT_add(self.group, self.F, self.F, temp, 0) + + # ... + c*G + OpenSSL.EC_POINT_mul(self.group, temp, 0, self.G, self.c, 0) + OpenSSL.EC_POINT_add(self.group, self.F, self.F, temp, 0) + + # F = (x0, y0) + x0 = OpenSSL.BN_new() + y0 = OpenSSL.BN_new() + OpenSSL.EC_POINT_get_affine_coordinates_GFp(self.group, self.F, x0, y0, + self.ctx) + self.r = x0 + + # Requester: Blinding (m' = br(m) + a) + self.m = OpenSSL.BN_new() + OpenSSL.BN_bin2bn(msg, len(msg), self.m) + + self.m_ = OpenSSL.BN_new() + OpenSSL.BN_mod_mul(self.m_, self.b, self.r, self.n, self.ctx) + OpenSSL.BN_mod_mul(self.m_, self.m_, self.m, self.n, self.ctx) + OpenSSL.BN_mod_add(self.m_, self.m_, self.a, self.n, self.ctx) + + def blind_sign(self): + """ + Signer blind-signs the request + """ + self.s_ = OpenSSL.BN_new() + OpenSSL.BN_mod_mul(self.s_, self.keypair[0], self.m_, self.n, self.ctx) + OpenSSL.BN_mod_add(self.s_, self.s_, self.k, self.n, self.ctx) + + def unblind(self): + """ + Requester unblinds the signature + """ + s = OpenSSL.BN_new() + OpenSSL.BN_mod_mul(s, self.binv, self.s_, self.n, self.ctx) + OpenSSL.BN_mod_add(s, s, self.c, self.n, self.ctx) + self.signature = (s, self.F) + + def verify(self): + """ + Verify signature with certifier's pubkey + """ + lhs = OpenSSL.EC_POINT_new(self.group) + rhs = OpenSSL.EC_POINT_new(self.group) + + OpenSSL.EC_POINT_mul(self.group, lhs, self.signature[0], 0, 0, 0) + OpenSSL.EC_POINT_mul(self.group, rhs, 0, self.Q, self.m, 0) + OpenSSL.EC_POINT_mul(self.group, rhs, 0, rhs, self.r, 0) + OpenSSL.EC_POINT_add(self.group, rhs, rhs, self.F, self.ctx) + + retval = OpenSSL.EC_POINT_cmp(self.group, lhs, rhs, self.ctx) + if retval == -1: + raise RuntimeError("EC_POINT_cmp returned an error") + else: + return retval == 0 diff --git a/src/pyelliptic/hash.py b/src/pyelliptic/hash.py index fb910dd4..f2240500 100644 --- a/src/pyelliptic/hash.py +++ b/src/pyelliptic/hash.py @@ -4,7 +4,7 @@ # Copyright (C) 2011 Yann GUIBET # See LICENSE for details. -from pyelliptic.openssl import OpenSSL +from openssl import OpenSSL # For python3 diff --git a/src/pyelliptic/openssl.py b/src/pyelliptic/openssl.py index 115bdc08..ab2990e6 100644 --- a/src/pyelliptic/openssl.py +++ b/src/pyelliptic/openssl.py @@ -19,7 +19,9 @@ class CipherName: self._blocksize = blocksize def __str__(self): - return "Cipher : " + self._name + " | Blocksize : " + str(self._blocksize) + " | Fonction pointer : " + str(self._pointer) + return "Cipher : " + self._name + \ + " | Blocksize : " + str(self._blocksize) + \ + " | Function pointer : " + str(self._pointer) def get_pointer(self): return self._pointer() @@ -36,7 +38,7 @@ def get_version(library): hexversion = None cflags = None try: - #OpenSSL 1.1 + # OpenSSL 1.1 OPENSSL_VERSION = 0 OPENSSL_CFLAGS = 1 library.OpenSSL_version.argtypes = [ctypes.c_int] @@ -47,7 +49,7 @@ def get_version(library): hexversion = library.OpenSSL_version_num() except AttributeError: try: - #OpenSSL 1.0 + # OpenSSL 1.0 SSLEAY_VERSION = 0 SSLEAY_CFLAGS = 2 library.SSLeay.restype = ctypes.c_long @@ -57,7 +59,7 @@ def get_version(library): cflags = library.SSLeay_version(SSLEAY_CFLAGS) hexversion = library.SSLeay() except AttributeError: - #raise NotImplementedError('Cannot determine version of this OpenSSL library.') + # raise NotImplementedError('Cannot determine version of this OpenSSL library.') pass return (version, hexversion, cflags) @@ -130,7 +132,11 @@ class _OpenSSL: 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 = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] + self.EC_POINT_get_affine_coordinates_GFp.argtypes = [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 @@ -144,11 +150,16 @@ class _OpenSSL: 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_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 = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] + self.EC_POINT_set_affine_coordinates_GFp.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] self.EC_POINT_new = self._lib.EC_POINT_new self.EC_POINT_new.restype = ctypes.c_void_p @@ -164,7 +175,11 @@ class _OpenSSL: self.EC_POINT_mul = self._lib.EC_POINT_mul self.EC_POINT_mul.restype = None - 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] + 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] self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key self.EC_KEY_set_private_key.restype = ctypes.c_int @@ -175,10 +190,11 @@ class _OpenSSL: self.EC_KEY_OpenSSL = self._lib.EC_KEY_OpenSSL self._lib.EC_KEY_OpenSSL.restype = ctypes.c_void_p self._lib.EC_KEY_OpenSSL.argtypes = [] - + self.EC_KEY_set_method = self._lib.EC_KEY_set_method self._lib.EC_KEY_set_method.restype = ctypes.c_int - self._lib.EC_KEY_set_method.argtypes = [ctypes.c_void_p, ctypes.c_void_p] + self._lib.EC_KEY_set_method.argtypes = [ctypes.c_void_p, + ctypes.c_void_p] else: self.ECDH_OpenSSL = self._lib.ECDH_OpenSSL self._lib.ECDH_OpenSSL.restype = ctypes.c_void_p @@ -186,7 +202,8 @@ class _OpenSSL: 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._lib.ECDH_set_method.argtypes = [ctypes.c_void_p, + ctypes.c_void_p] self.BN_CTX_new = self._lib.BN_CTX_new self._lib.BN_CTX_new.restype = ctypes.c_void_p @@ -195,12 +212,15 @@ class _OpenSSL: 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] + 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] + 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 @@ -223,13 +243,13 @@ class _OpenSSL: self.EVP_aes_256_cbc.restype = ctypes.c_void_p self.EVP_aes_256_cbc.argtypes = [] - #self.EVP_aes_128_ctr = self._lib.EVP_aes_128_ctr - #self.EVP_aes_128_ctr.restype = ctypes.c_void_p - #self.EVP_aes_128_ctr.argtypes = [] + # self.EVP_aes_128_ctr = self._lib.EVP_aes_128_ctr + # self.EVP_aes_128_ctr.restype = ctypes.c_void_p + # self.EVP_aes_128_ctr.argtypes = [] - #self.EVP_aes_256_ctr = self._lib.EVP_aes_256_ctr - #self.EVP_aes_256_ctr.restype = ctypes.c_void_p - #self.EVP_aes_256_ctr.argtypes = [] + # self.EVP_aes_256_ctr = self._lib.EVP_aes_256_ctr + # 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 @@ -250,7 +270,7 @@ class _OpenSSL: self.EVP_rc4 = self._lib.EVP_rc4 self.EVP_rc4.restype = ctypes.c_void_p self.EVP_rc4.argtypes = [] - + if self._hexversion >= 0x10100000 and not self._libreSSL: self.EVP_CIPHER_CTX_reset = self._lib.EVP_CIPHER_CTX_reset self.EVP_CIPHER_CTX_reset.restype = ctypes.c_int @@ -281,7 +301,7 @@ class _OpenSSL: 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, @@ -296,7 +316,7 @@ class _OpenSSL: 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.ECDSA_sign = self._lib.ECDSA_sign self.ECDSA_sign.restype = ctypes.c_int self.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p, @@ -311,7 +331,7 @@ class _OpenSSL: self.EVP_MD_CTX_new = self._lib.EVP_MD_CTX_new self.EVP_MD_CTX_new.restype = ctypes.c_void_p self.EVP_MD_CTX_new.argtypes = [] - + self.EVP_MD_CTX_reset = self._lib.EVP_MD_CTX_reset self.EVP_MD_CTX_reset.restype = None self.EVP_MD_CTX_reset.argtypes = [ctypes.c_void_p] @@ -329,11 +349,11 @@ class _OpenSSL: 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] @@ -370,13 +390,131 @@ class _OpenSSL: 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] + # Blind signature requirements + self.BN_CTX_new = self._lib.BN_CTX_new + self.BN_CTX_new.restype = ctypes.c_void_p + self.BN_CTX_new.argtypes = [] + + self.BN_dup = self._lib.BN_dup + self.BN_dup.restype = ctypes.c_void_p + self.BN_dup.argtypes = [ctypes.c_void_p] + + self.BN_rand = self._lib.BN_rand + self.BN_rand.restype = ctypes.c_int + self.BN_rand.argtypes = [ctypes.c_void_p, + ctypes.c_int, + ctypes.c_int] + + self.BN_set_word = self._lib.BN_set_word + self.BN_set_word.restype = ctypes.c_int + self.BN_set_word.argtypes = [ctypes.c_void_p, + ctypes.c_ulong] + + self.BN_mul = self._lib.BN_mul + self.BN_mul.restype = ctypes.c_int + self.BN_mul.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] + + self.BN_mod_add = self._lib.BN_mod_add + self.BN_mod_add.restype = ctypes.c_int + self.BN_mod_add.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] + + self.BN_mod_inverse = self._lib.BN_mod_inverse + self.BN_mod_inverse.restype = ctypes.c_void_p + self.BN_mod_inverse.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] + + self.BN_mod_mul = self._lib.BN_mod_mul + self.BN_mod_mul.restype = ctypes.c_int + self.BN_mod_mul.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] + + self.BN_lshift = self._lib.BN_lshift + self.BN_lshift.restype = ctypes.c_int + self.BN_lshift.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_int] + + self.BN_sub_word = self._lib.BN_sub_word + self.BN_sub_word.restype = ctypes.c_int + self.BN_sub_word.argtypes = [ctypes.c_void_p, + ctypes.c_ulong] + + self.BN_cmp = self._lib.BN_cmp + self.BN_cmp.restype = ctypes.c_int + self.BN_cmp.argtypes = [ctypes.c_void_p, + ctypes.c_void_p] + + self.BN_bn2dec = self._lib.BN_bn2dec + self.BN_bn2dec.restype = ctypes.c_char_p + self.BN_bn2dec.argtypes = [ctypes.c_void_p] + + self.BN_CTX_free = self._lib.BN_CTX_free + self.BN_CTX_free.argtypes = [ctypes.c_void_p] + + self.EC_GROUP_new_by_curve_name = self._lib.EC_GROUP_new_by_curve_name + self.EC_GROUP_new_by_curve_name.restype = ctypes.c_void_p + self.EC_GROUP_new_by_curve_name.argtypes = [ctypes.c_int] + + self.EC_GROUP_get_order = self._lib.EC_GROUP_get_order + self.EC_GROUP_get_order.restype = ctypes.c_int + self.EC_GROUP_get_order.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] + + self.EC_GROUP_get_cofactor = self._lib.EC_GROUP_get_cofactor + self.EC_GROUP_get_cofactor.restype = ctypes.c_int + self.EC_GROUP_get_cofactor.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] + + self.EC_GROUP_get0_generator = self._lib.EC_GROUP_get0_generator + self.EC_GROUP_get0_generator.restype = ctypes.c_void_p + self.EC_GROUP_get0_generator.argtypes = [ctypes.c_void_p] + + self.EC_POINT_copy = self._lib.EC_POINT_copy + self.EC_POINT_copy.restype = ctypes.c_int + self.EC_POINT_copy.argtypes = [ctypes.c_void_p, + ctypes.c_void_p] + + self.EC_POINT_add = self._lib.EC_POINT_add + self.EC_POINT_add.restype = ctypes.c_int + self.EC_POINT_add.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] + + self.EC_POINT_cmp = self._lib.EC_POINT_cmp + self.EC_POINT_cmp.restype = ctypes.c_int + self.EC_POINT_cmp.argtypes = [ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p] + + self.EC_POINT_set_to_infinity = self._lib.EC_POINT_set_to_infinity + self.EC_POINT_set_to_infinity.restype = ctypes.c_int + self.EC_POINT_set_to_infinity.argtypes = [ctypes.c_void_p, + ctypes.c_void_p] + self._set_ciphers() self._set_curves() @@ -388,11 +526,11 @@ class _OpenSSL: '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), + # '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), # 128 is the initialisation size not block size + 'rc4': CipherName('rc4', self.EVP_rc4, 128), # 128 is the initialisation size not block size } def _set_curves(self): @@ -470,11 +608,11 @@ class _OpenSSL: OpenSSL random function """ buffer = self.malloc(0, size) - # This pyelliptic library, by default, didn't check the return value of RAND_bytes. It is + # This pyelliptic library, by default, didn't check the return value of RAND_bytes. It is # evidently possible that it returned an error and not-actually-random data. However, in - # tests on various operating systems, while generating hundreds of gigabytes of random + # tests on various operating systems, while generating hundreds of gigabytes of random # strings of various sizes I could not get an error to occur. Also Bitcoin doesn't check - # the return value of RAND_bytes either. + # the return value of RAND_bytes either. # Fixed in Bitmessage version 0.4.2 (in source code on 2013-10-13) while self.RAND_bytes(buffer, size) != 1: import time @@ -494,22 +632,23 @@ class _OpenSSL: buffer = self.create_string_buffer(size) return buffer + def loadOpenSSL(): global OpenSSL from os import path, environ from ctypes.util import find_library - + libdir = [] - if getattr(sys,'frozen', None): + if getattr(sys, 'frozen', None): if 'darwin' in sys.platform: libdir.extend([ - path.join(environ['RESOURCEPATH'], '..', 'Frameworks','libcrypto.dylib'), - path.join(environ['RESOURCEPATH'], '..', 'Frameworks','libcrypto.1.1.0.dylib'), - path.join(environ['RESOURCEPATH'], '..', 'Frameworks','libcrypto.1.0.2.dylib'), - path.join(environ['RESOURCEPATH'], '..', 'Frameworks','libcrypto.1.0.1.dylib'), - path.join(environ['RESOURCEPATH'], '..', 'Frameworks','libcrypto.1.0.0.dylib'), - path.join(environ['RESOURCEPATH'], '..', 'Frameworks','libcrypto.0.9.8.dylib'), - ]) + path.join(environ['RESOURCEPATH'], '..', 'Frameworks', 'libcrypto.dylib'), + path.join(environ['RESOURCEPATH'], '..', 'Frameworks', 'libcrypto.1.1.0.dylib'), + path.join(environ['RESOURCEPATH'], '..', 'Frameworks', 'libcrypto.1.0.2.dylib'), + path.join(environ['RESOURCEPATH'], '..', 'Frameworks', 'libcrypto.1.0.1.dylib'), + path.join(environ['RESOURCEPATH'], '..', 'Frameworks', 'libcrypto.1.0.0.dylib'), + path.join(environ['RESOURCEPATH'], '..', 'Frameworks', 'libcrypto.0.9.8.dylib'), + ]) elif 'win32' in sys.platform or 'win64' in sys.platform: libdir.append(path.join(sys._MEIPASS, 'libeay32.dll')) else: @@ -548,4 +687,5 @@ def loadOpenSSL(): pass raise Exception("Couldn't find and load the OpenSSL library. You must install it.") + loadOpenSSL() diff --git a/src/tests/test_blindsig.py b/src/tests/test_blindsig.py new file mode 100644 index 00000000..737ee485 --- /dev/null +++ b/src/tests/test_blindsig.py @@ -0,0 +1,22 @@ +""" +Test for ECC blind signatures +""" +import os +import unittest + +from src.pyelliptic.eccblind import ECCBlind + + +class TestBlindSig(unittest.TestCase): + """ + Test case for ECC blind signature + """ + def test_blind_sig(self): + """Test full sequence using a random certifier key and a random message""" + blind_sig = ECCBlind() + blind_sig.signer_init() + msg = os.urandom(64) + blind_sig.create_signing_request(msg) + blind_sig.blind_sign() + blind_sig.unblind() + self.assertTrue(blind_sig.verify())