From 6ebf8666dc83d3e45e83a4308f3aea59ea56c88a Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Fri, 27 Mar 2015 15:25:32 -0400 Subject: [PATCH] support SHA256 signatures --- src/highlevelcrypto.py | 21 +++++++++++++++++++-- src/pyelliptic/ecc.py | 12 ++++++------ src/pyelliptic/openssl.py | 9 +++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/highlevelcrypto.py b/src/highlevelcrypto.py index f357735f..5a2ae920 100644 --- a/src/highlevelcrypto.py +++ b/src/highlevelcrypto.py @@ -30,11 +30,28 @@ def decryptFast(msg,cryptor): return cryptor.decrypt(msg) # Signs with hex private key def sign(msg,hexPrivkey): - return makeCryptor(hexPrivkey).sign(msg) + # pyelliptic is upgrading from SHA1 to SHA256 for signing. We must + # upgrade PyBitmessage gracefully. + # https://github.com/yann2192/pyelliptic/pull/33 + # More discussion: https://github.com/yann2192/pyelliptic/issues/32 + return makeCryptor(hexPrivkey).sign(msg, digest_alg=OpenSSL.EVP_ecdsa) # SHA1 + #return makeCryptor(hexPrivkey).sign(msg, digest_alg=OpenSSL.EVP_sha256) # SHA256. We should switch to this eventually. # Verifies with hex public key def verify(msg,sig,hexPubkey): + # As mentioned above, we must upgrade gracefully to use SHA256. So + # let us check the signature using both SHA1 and SHA256 and if one + # of them passes then we will be satisfied. Eventually this can + # be simplified and we'll only check with SHA256. try: - return makePubCryptor(hexPubkey).verify(sig,msg) + sigVerifyPassed = makePubCryptor(hexPubkey).verify(sig,msg,digest_alg=OpenSSL.EVP_ecdsa) # old SHA1 algorithm. + except: + sigVerifyPassed = False + if sigVerifyPassed: + # The signature check passed using SHA1 + return True + # The signature check using SHA1 failed. Let us try it with SHA256. + try: + return makePubCryptor(hexPubkey).verify(sig,msg,digest_alg=OpenSSL.EVP_sha256) except: return False diff --git a/src/pyelliptic/ecc.py b/src/pyelliptic/ecc.py index 44020be2..269db952 100644 --- a/src/pyelliptic/ecc.py +++ b/src/pyelliptic/ecc.py @@ -299,7 +299,7 @@ class ECC: if privkey is not None: OpenSSL.BN_free(priv_key) - def sign(self, inputb): + def sign(self, inputb, digest_alg=OpenSSL.EVP_ecdsa): """ Sign the input with ECDSA method and returns the signature """ @@ -338,11 +338,11 @@ class ECC: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") OpenSSL.EVP_MD_CTX_init(md_ctx) - OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa()) + OpenSSL.EVP_DigestInit_ex(md_ctx, digest_alg(), None) if (OpenSSL.EVP_DigestUpdate(md_ctx, buff, size)) == 0: raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...") - OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len) + 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: @@ -358,7 +358,7 @@ class ECC: OpenSSL.EC_POINT_free(pub_key) OpenSSL.EVP_MD_CTX_destroy(md_ctx) - def verify(self, sig, inputb): + def verify(self, sig, inputb, digest_alg=OpenSSL.EVP_ecdsa): """ Verify the signature with the input and the local public key. Returns a boolean @@ -392,11 +392,11 @@ class ECC: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") OpenSSL.EVP_MD_CTX_init(md_ctx) - OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa()) + OpenSSL.EVP_DigestInit_ex(md_ctx, digest_alg(), None) if (OpenSSL.EVP_DigestUpdate(md_ctx, binputb, len(inputb))) == 0: raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...") - OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len) + OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len) ret = OpenSSL.ECDSA_verify( 0, digest, dgst_len.contents, bsig, len(sig), key) diff --git a/src/pyelliptic/openssl.py b/src/pyelliptic/openssl.py index f83630d4..c6b72b65 100644 --- a/src/pyelliptic/openssl.py +++ b/src/pyelliptic/openssl.py @@ -231,6 +231,10 @@ class _OpenSSL: self.EVP_DigestInit.restype = ctypes.c_int self._lib.EVP_DigestInit.argtypes = [ctypes.c_void_p, 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, @@ -241,6 +245,11 @@ class _OpenSSL: 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 = []