diff --git a/electrum/bitcoin.py b/electrum/bitcoin.py index 3066692c9..41e83c53d 100644 --- a/electrum/bitcoin.py +++ b/electrum/bitcoin.py @@ -31,7 +31,7 @@ from . import version from . import segwit_addr from . import constants from . import ecc -from .crypto import Hash, sha256, hash_160, hmac_oneshot +from .crypto import sha256d, sha256, hash_160, hmac_oneshot ################################## transactions @@ -199,7 +199,7 @@ is_seed = lambda x: bool(seed_type(x)) def hash160_to_b58_address(h160: bytes, addrtype): s = bytes([addrtype]) s += h160 - return base_encode(s+Hash(s)[0:4], base=58) + return base_encode(s+sha256d(s)[0:4], base=58) def b58_address_to_hash160(addr): @@ -382,7 +382,7 @@ class InvalidChecksum(Exception): def EncodeBase58Check(vchIn): - hash = Hash(vchIn) + hash = sha256d(vchIn) return base_encode(vchIn + hash[0:4], base=58) @@ -390,7 +390,7 @@ def DecodeBase58Check(psz): vchRet = base_decode(psz, None, base=58) key = vchRet[0:-4] csum = vchRet[-4:] - hash = Hash(key) + hash = sha256d(key) cs32 = hash[0:4] if cs32 != csum: raise InvalidChecksum('expected {}, actual {}'.format(bh2u(cs32), bh2u(csum))) diff --git a/electrum/blockchain.py b/electrum/blockchain.py index ccc04138b..0f8749056 100644 --- a/electrum/blockchain.py +++ b/electrum/blockchain.py @@ -25,7 +25,8 @@ import threading from typing import Optional, Dict from . import util -from .bitcoin import Hash, hash_encode, int_to_hex, rev_hex +from .bitcoin import hash_encode, int_to_hex, rev_hex +from .crypto import sha256d from . import constants from .util import bfh, bh2u from .simple_config import SimpleConfig @@ -71,7 +72,7 @@ def hash_header(header: dict) -> str: return '0' * 64 if header.get('prev_block_hash') is None: header['prev_block_hash'] = '00'*32 - return hash_encode(Hash(bfh(serialize_header(header)))) + return hash_encode(sha256d(bfh(serialize_header(header)))) blockchains = {} # type: Dict[int, Blockchain] diff --git a/electrum/crypto.py b/electrum/crypto.py index de8b6b5d7..417a433bc 100644 --- a/electrum/crypto.py +++ b/electrum/crypto.py @@ -27,6 +27,7 @@ import base64 import os import hashlib import hmac +from typing import Union import pyaes @@ -104,14 +105,14 @@ def DecodeAES(secret, e): def pw_encode(s, password): if password: - secret = Hash(password) + secret = sha256d(password) return EncodeAES(secret, to_bytes(s, "utf8")).decode('utf8') else: return s def pw_decode(s, password): if password is not None: - secret = Hash(password) + secret = sha256d(password) try: d = to_string(DecodeAES(secret, s), "utf8") except Exception: @@ -121,12 +122,12 @@ def pw_decode(s, password): return s -def sha256(x: bytes) -> bytes: +def sha256(x: Union[bytes, str]) -> bytes: x = to_bytes(x, 'utf8') return bytes(hashlib.sha256(x).digest()) -def Hash(x: bytes) -> bytes: +def sha256d(x: Union[bytes, str]) -> bytes: x = to_bytes(x, 'utf8') out = bytes(sha256(sha256(x))) return out diff --git a/electrum/ecc.py b/electrum/ecc.py index c5e77278f..4a3cd2e97 100644 --- a/electrum/ecc.py +++ b/electrum/ecc.py @@ -34,7 +34,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, hmac_oneshot) +from .crypto import (sha256d, aes_encrypt_with_iv, aes_decrypt_with_iv, hmac_oneshot) from .ecc_fast import do_monkey_patching_of_python_ecdsa_internals_with_libsecp256k1 from . import msqr @@ -252,7 +252,7 @@ class ECPubkey(object): def verify_message_for_address(self, sig65: bytes, message: bytes) -> None: assert_bytes(message) - h = Hash(msg_magic(message)) + h = sha256d(msg_magic(message)) public_key, compressed = self.from_signature65(sig65, h) # check public key if public_key != self: @@ -313,7 +313,7 @@ def verify_message_with_address(address: str, sig65: bytes, message: bytes): from .bitcoin import pubkey_to_address assert_bytes(sig65, message) try: - h = Hash(msg_magic(message)) + h = sha256d(msg_magic(message)) public_key, compressed = ECPubkey.from_signature65(sig65, h) # check public key using the address pubkey_hex = public_key.get_public_key_hex(compressed) @@ -403,7 +403,7 @@ class ECPrivkey(ECPubkey): raise Exception("error: cannot sign message. no recid fits..") message = to_bytes(message, 'utf8') - msg_hash = Hash(msg_magic(message)) + msg_hash = sha256d(msg_magic(message)) sig_string = self.sign(msg_hash, sigencode=sig_string_from_r_and_s, sigdecode=get_r_and_s_from_sig_string) diff --git a/electrum/keystore.py b/electrum/keystore.py index f991a4f5d..a942d0751 100644 --- a/electrum/keystore.py +++ b/electrum/keystore.py @@ -35,7 +35,7 @@ from .bip32 import (bip32_public_derivation, deserialize_xpub, CKD_pub, bip32_private_key, bip32_derivation, BIP32_PRIME, is_xpub, is_xprv) from .ecc import string_to_number, number_to_string -from .crypto import pw_decode, pw_encode, Hash +from .crypto import pw_decode, pw_encode, sha256d from .util import (PrintError, InvalidPassword, hfu, WalletFileException, BitcoinException, bh2u, bfh, print_error, inv_dict) from .mnemonic import Mnemonic, load_wordlist @@ -413,7 +413,7 @@ class Old_KeyStore(Deterministic_KeyStore): @classmethod def get_sequence(self, mpk, for_change, n): - return string_to_number(Hash(("%d:%d:"%(n, for_change)).encode('ascii') + bfh(mpk))) + return string_to_number(sha256d(("%d:%d:"%(n, for_change)).encode('ascii') + bfh(mpk))) @classmethod def get_pubkey_from_mpk(self, mpk, for_change, n): diff --git a/electrum/plugins/cosigner_pool/qt.py b/electrum/plugins/cosigner_pool/qt.py index 0f9d4fb37..175e469cc 100644 --- a/electrum/plugins/cosigner_pool/qt.py +++ b/electrum/plugins/cosigner_pool/qt.py @@ -133,7 +133,7 @@ class Plugin(BasePlugin): for key, keystore in wallet.keystores.items(): xpub = keystore.get_master_public_key() K = bip32.deserialize_xpub(xpub)[-1] - _hash = bh2u(crypto.Hash(K)) + _hash = bh2u(crypto.sha256d(K)) if not keystore.is_watching_only(): self.keys.append((key, _hash, window)) else: diff --git a/electrum/plugins/digitalbitbox/digitalbitbox.py b/electrum/plugins/digitalbitbox/digitalbitbox.py index 24f676e0e..bb9131c3d 100644 --- a/electrum/plugins/digitalbitbox/digitalbitbox.py +++ b/electrum/plugins/digitalbitbox/digitalbitbox.py @@ -4,7 +4,7 @@ # try: - from electrum.crypto import Hash, EncodeAES, DecodeAES + from electrum.crypto import sha256d, EncodeAES, DecodeAES from electrum.bitcoin import (TYPE_ADDRESS, push_script, var_int, public_key_to_p2pkh, is_address) from electrum.bip32 import serialize_xpub, deserialize_xpub @@ -395,7 +395,7 @@ class DigitalBitbox_Client(): def hid_send_encrypt(self, msg): reply = "" try: - secret = Hash(self.password) + secret = sha256d(self.password) msg = EncodeAES(secret, msg) reply = self.hid_send_plain(msg) if 'ciphertext' in reply: @@ -448,7 +448,7 @@ class DigitalBitbox_KeyStore(Hardware_KeyStore): try: message = message.encode('utf8') inputPath = self.get_derivation() + "/%d/%d" % sequence - msg_hash = Hash(msg_magic(message)) + msg_hash = sha256d(msg_magic(message)) inputHash = to_hexstr(msg_hash) hasharray = [] hasharray.append({'hash': inputHash, 'keypath': inputPath}) @@ -526,7 +526,7 @@ class DigitalBitbox_KeyStore(Hardware_KeyStore): if x_pubkey in derivations: index = derivations.get(x_pubkey) inputPath = "%s/%d/%d" % (self.get_derivation(), index[0], index[1]) - inputHash = Hash(binascii.unhexlify(tx.serialize_preimage(i))) + inputHash = sha256d(binascii.unhexlify(tx.serialize_preimage(i))) hasharray_i = {'hash': to_hexstr(inputHash), 'keypath': inputPath} hasharray.append(hasharray_i) inputhasharray.append(inputHash) @@ -577,7 +577,7 @@ class DigitalBitbox_KeyStore(Hardware_KeyStore): }, } if tx_dbb_serialized is not None: - msg["sign"]["meta"] = to_hexstr(Hash(tx_dbb_serialized)) + msg["sign"]["meta"] = to_hexstr(sha256d(tx_dbb_serialized)) msg = json.dumps(msg).encode('ascii') dbb_client = self.plugin.get_client(self) diff --git a/electrum/tests/test_bitcoin.py b/electrum/tests/test_bitcoin.py index 399ffc2e2..e11cee4ec 100644 --- a/electrum/tests/test_bitcoin.py +++ b/electrum/tests/test_bitcoin.py @@ -11,7 +11,7 @@ from electrum.bitcoin import (public_key_to_p2pkh, address_from_private_key, from electrum.bip32 import (bip32_root, bip32_public_derivation, bip32_private_derivation, xpub_from_xprv, xpub_type, is_xprv, is_bip32_derivation, is_xpub, convert_bip32_path_to_list_of_uint32) -from electrum.crypto import Hash +from electrum.crypto import sha256d from electrum import ecc, crypto, constants from electrum.ecc import number_to_string, string_to_number from electrum.transaction import opcodes @@ -246,13 +246,9 @@ class Test_bitcoin(SequentialTestCase): enc = crypto.pw_encode(payload, password) self.assertRaises(Exception, crypto.pw_decode, enc, wrong_password) - def test_hash(self): - """Make sure the Hash function does sha256 twice""" - payload = u"test" - expected = b'\x95MZI\xfdp\xd9\xb8\xbc\xdb5\xd2R&x)\x95\x7f~\xf7\xfalt\xf8\x84\x19\xbd\xc5\xe8"\t\xf4' - - result = Hash(payload) - self.assertEqual(expected, result) + def test_sha256d(self): + self.assertEqual(b'\x95MZI\xfdp\xd9\xb8\xbc\xdb5\xd2R&x)\x95\x7f~\xf7\xfalt\xf8\x84\x19\xbd\xc5\xe8"\t\xf4', + sha256d(u"test")) def test_int_to_hex(self): self.assertEqual('00', int_to_hex(0, 1)) diff --git a/electrum/transaction.py b/electrum/transaction.py index 96bf6f991..b9134eaab 100644 --- a/electrum/transaction.py +++ b/electrum/transaction.py @@ -39,7 +39,7 @@ from .bitcoin import (TYPE_ADDRESS, TYPE_PUBKEY, TYPE_SCRIPT, hash_160, hash160_to_p2sh, hash160_to_p2pkh, hash_to_segwit_addr, hash_encode, var_int, TOTAL_COIN_SUPPLY_LIMIT_IN_BTC, COIN, op_push, int_to_hex, push_script, b58_address_to_hash160) -from .crypto import Hash +from .crypto import sha256d from .keystore import xpubkey_to_address, xpubkey_to_pubkey @@ -728,7 +728,7 @@ class Transaction: sig = signatures[i] if sig in txin.get('signatures'): continue - pre_hash = Hash(bfh(self.serialize_preimage(i))) + pre_hash = sha256d(bfh(self.serialize_preimage(i))) sig_string = ecc.sig_string_from_der_sig(bfh(sig[:-2])) for recid in range(4): try: @@ -1036,9 +1036,9 @@ class Transaction: txin = inputs[i] # TODO: py3 hex if self.is_segwit_input(txin): - hashPrevouts = bh2u(Hash(bfh(''.join(self.serialize_outpoint(txin) for txin in inputs)))) - hashSequence = bh2u(Hash(bfh(''.join(int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) for txin in inputs)))) - hashOutputs = bh2u(Hash(bfh(''.join(self.serialize_output(o) for o in outputs)))) + hashPrevouts = bh2u(sha256d(bfh(''.join(self.serialize_outpoint(txin) for txin in inputs)))) + hashSequence = bh2u(sha256d(bfh(''.join(int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) for txin in inputs)))) + hashOutputs = bh2u(sha256d(bfh(''.join(self.serialize_output(o) for o in outputs)))) outpoint = self.serialize_outpoint(txin) preimage_script = self.get_preimage_script(txin) scriptCode = var_int(len(preimage_script) // 2) + preimage_script @@ -1091,14 +1091,14 @@ class Transaction: if not all_segwit and not self.is_complete(): return None ser = self.serialize_to_network(witness=False) - return bh2u(Hash(bfh(ser))[::-1]) + return bh2u(sha256d(bfh(ser))[::-1]) def wtxid(self): self.deserialize() if not self.is_complete(): return None ser = self.serialize_to_network(witness=True) - return bh2u(Hash(bfh(ser))[::-1]) + return bh2u(sha256d(bfh(ser))[::-1]) def add_inputs(self, inputs): self._inputs.extend(inputs) @@ -1219,7 +1219,7 @@ class Transaction: self.raw = self.serialize() def sign_txin(self, txin_index, privkey_bytes) -> str: - pre_hash = Hash(bfh(self.serialize_preimage(txin_index))) + pre_hash = sha256d(bfh(self.serialize_preimage(txin_index))) privkey = ecc.ECPrivkey(privkey_bytes) sig = privkey.sign_transaction(pre_hash) sig = bh2u(sig) + '01' diff --git a/electrum/verifier.py b/electrum/verifier.py index 32ea4aa41..27913ce13 100644 --- a/electrum/verifier.py +++ b/electrum/verifier.py @@ -27,7 +27,7 @@ from typing import Sequence, Optional, TYPE_CHECKING import aiorpcx from .util import bh2u, VerifiedTxInfo, NetworkJobOnDefaultServer -from .crypto import Hash +from .crypto import sha256d from .bitcoin import hash_decode, hash_encode from .transaction import Transaction from .blockchain import hash_header @@ -140,7 +140,7 @@ class SPV(NetworkJobOnDefaultServer): raise MerkleVerificationFailure(e) for i, item in enumerate(merkle_branch_bytes): - h = Hash(item + h) if ((leaf_pos_in_tree >> i) & 1) else Hash(h + item) + h = sha256d(item + h) if ((leaf_pos_in_tree >> i) & 1) else sha256d(h + item) cls._raise_if_valid_tx(bh2u(h)) return hash_encode(h) diff --git a/electrum/wallet.py b/electrum/wallet.py index 6379ef43c..94486eb21 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -48,7 +48,7 @@ from .util import (NotEnoughFunds, PrintError, UserCancelled, profiler, from .bitcoin import (COIN, TYPE_ADDRESS, is_address, address_to_script, is_minikey) from .version import * -from .crypto import Hash +from .crypto import sha256d from .keystore import load_keystore, Hardware_KeyStore from .storage import multisig_type, STO_EV_PLAINTEXT, STO_EV_USER_PW, STO_EV_XPUB_PW, WalletStorage from . import transaction, bitcoin, coinchooser, paymentrequest, ecc, bip32 @@ -931,7 +931,7 @@ class Abstract_Wallet(AddressSynchronizer): def make_payment_request(self, addr, amount, message, expiration): timestamp = int(time.time()) - _id = bh2u(Hash(addr + "%d"%timestamp))[0:10] + _id = bh2u(sha256d(addr + "%d"%timestamp))[0:10] r = {'time':timestamp, 'amount':amount, 'exp':expiration, 'address':addr, 'memo':message, 'id':_id} return r