URI: 
       tfast hmac on python 3.7+ - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit bc0036297b906bc53ce3886ea146c752e47e1ce9
   DIR parent 2b93593e3fe278f62d4e1625437153813dde76ed
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Thu, 28 Jun 2018 11:42:47 +0200
       
       fast hmac on python 3.7+
       
       Diffstat:
         M lib/bitcoin.py                      |      10 +++++-----
         M lib/crypto.py                       |       9 +++++++++
         M lib/ecc.py                          |       6 +++---
       
       3 files changed, 17 insertions(+), 8 deletions(-)
       ---
   DIR diff --git a/lib/bitcoin.py b/lib/bitcoin.py
       t@@ -31,7 +31,7 @@ from . import version
        from . import segwit_addr
        from . import constants
        from . import ecc
       -from .crypto import Hash, sha256, hash_160
       +from .crypto import Hash, sha256, hash_160, hmac_oneshot
        
        
        ################################## transactions
       t@@ -149,7 +149,7 @@ def add_number_to_script(i: int) -> bytes:
        
        hash_encode = lambda x: bh2u(x[::-1])
        hash_decode = lambda x: bfh(x)[::-1]
       -hmac_sha_512 = lambda x, y: hmac.new(x, y, hashlib.sha512).digest()
       +hmac_sha_512 = lambda x, y: hmac_oneshot(x, y, hashlib.sha512)
        
        
        def is_new_seed(x, prefix=version.SEED_PREFIX):
       t@@ -565,7 +565,7 @@ def _CKD_priv(k, c, s, is_prime):
                raise BitcoinException('Impossible xprv (not within curve order)') from e
            cK = keypair.get_public_key_bytes(compressed=True)
            data = bytes([0]) + k + s if is_prime else cK + s
       -    I = hmac.new(c, data, hashlib.sha512).digest()
       +    I = hmac_oneshot(c, data, hashlib.sha512)
            I_left = ecc.string_to_number(I[0:32])
            k_n = (I_left + ecc.string_to_number(k)) % ecc.CURVE_ORDER
            if I_left >= ecc.CURVE_ORDER or k_n == 0:
       t@@ -589,7 +589,7 @@ def CKD_pub(cK, c, n):
        # helper function, callable with arbitrary string.
        # note: 's' does not need to fit into 32 bits here! (c.f. trustedcoin billing)
        def _CKD_pub(cK, c, s):
       -    I = hmac.new(c, cK + s, hashlib.sha512).digest()
       +    I = hmac_oneshot(c, cK + s, hashlib.sha512)
            pubkey = ecc.ECPrivkey(I[0:32]) + ecc.ECPubkey(cK)
            if pubkey.is_at_infinity():
                raise ecc.InvalidECPointException()
       t@@ -683,7 +683,7 @@ def xpub_from_xprv(xprv):
        
        
        def bip32_root(seed, xtype):
       -    I = hmac.new(b"Bitcoin seed", seed, hashlib.sha512).digest()
       +    I = hmac_oneshot(b"Bitcoin seed", seed, hashlib.sha512)
            master_k = I[0:32]
            master_c = I[32:]
            # create xprv first, as that will check if master_k is within curve order
   DIR diff --git a/lib/crypto.py b/lib/crypto.py
       t@@ -26,6 +26,7 @@
        import base64
        import os
        import hashlib
       +import hmac
        
        import pyaes
        
       t@@ -140,3 +141,11 @@ def hash_160(x: bytes) -> bytes:
                from . import ripemd
                md = ripemd.new(sha256(x))
                return md.digest()
       +
       +
       +def hmac_oneshot(key: bytes, msg: bytes, digest) -> bytes:
       +    if hasattr(hmac, 'digest'):
       +        # requires python 3.7+; faster
       +        return hmac.digest(key, msg, digest)
       +    else:
       +        return hmac.new(key, msg, digest).digest()
   DIR diff --git a/lib/ecc.py b/lib/ecc.py
       t@@ -36,7 +36,7 @@ from ecdsa.ellipticcurve import Point
        from ecdsa.util import string_to_number, number_to_string
        
        from .util import bfh, bh2u, assert_bytes, print_error, to_bytes, InvalidPassword, profiler
       -from .crypto import (Hash, aes_encrypt_with_iv, aes_decrypt_with_iv)
       +from .crypto import (Hash, aes_encrypt_with_iv, aes_decrypt_with_iv, hmac_oneshot)
        from .ecc_fast import do_monkey_patching_of_python_ecdsa_internals_with_libsecp256k1
        
        
       t@@ -285,7 +285,7 @@ class ECPubkey(object):
                ciphertext = aes_encrypt_with_iv(key_e, iv, message)
                ephemeral_pubkey = ephemeral.get_public_key_bytes(compressed=True)
                encrypted = magic + ephemeral_pubkey + ciphertext
       -        mac = hmac.new(key_m, encrypted, hashlib.sha256).digest()
       +        mac = hmac_oneshot(key_m, encrypted, hashlib.sha256)
        
                return base64.b64encode(encrypted + mac)
        
       t@@ -424,7 +424,7 @@ class ECPrivkey(ECPubkey):
                ecdh_key = (ephemeral_pubkey * self.secret_scalar).get_public_key_bytes(compressed=True)
                key = hashlib.sha512(ecdh_key).digest()
                iv, key_e, key_m = key[0:16], key[16:32], key[32:]
       -        if mac != hmac.new(key_m, encrypted[:-32], hashlib.sha256).digest():
       +        if mac != hmac_oneshot(key_m, encrypted[:-32], hashlib.sha256):
                    raise InvalidPassword()
                return aes_decrypt_with_iv(key_e, iv, ciphertext)