ttest_bitcoin.py - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- ttest_bitcoin.py (53879B) --- 1 import base64 2 import sys 3 4 from electrum.bitcoin import (public_key_to_p2pkh, address_from_private_key, 5 is_address, is_private_key, 6 var_int, _op_push, address_to_script, 7 deserialize_privkey, serialize_privkey, is_segwit_address, 8 is_b58_address, address_to_scripthash, is_minikey, 9 is_compressed_privkey, EncodeBase58Check, DecodeBase58Check, 10 script_num_to_hex, push_script, add_number_to_script, int_to_hex, 11 opcodes, base_encode, base_decode, BitcoinException) 12 from electrum import bip32 13 from electrum.bip32 import (BIP32Node, convert_bip32_intpath_to_strpath, 14 xpub_from_xprv, xpub_type, is_xprv, is_bip32_derivation, 15 is_xpub, convert_bip32_path_to_list_of_uint32, 16 normalize_bip32_derivation, is_all_public_derivation) 17 from electrum.crypto import sha256d, SUPPORTED_PW_HASH_VERSIONS 18 from electrum import ecc, crypto, constants 19 from electrum.util import bfh, bh2u, InvalidPassword, randrange 20 from electrum.storage import WalletStorage 21 from electrum.keystore import xtype_from_derivation 22 23 from electrum import ecc_fast 24 25 from . import ElectrumTestCase 26 from . import TestCaseForTestnet 27 from . import FAST_TESTS 28 29 30 def needs_test_with_all_aes_implementations(func): 31 """Function decorator to run a unit test multiple times: 32 once with each AES implementation. 33 34 NOTE: this is inherently sequential; 35 tests running in parallel would break things 36 """ 37 def run_test(*args, **kwargs): 38 if FAST_TESTS: # if set, only run tests once, using fastest implementation 39 func(*args, **kwargs) 40 return 41 has_cryptodome = crypto.HAS_CRYPTODOME 42 has_cryptography = crypto.HAS_CRYPTOGRAPHY 43 has_pyaes = crypto.HAS_PYAES 44 try: 45 if has_pyaes: 46 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY, crypto.HAS_PYAES) = False, False, True 47 func(*args, **kwargs) # pyaes 48 if has_cryptodome: 49 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY, crypto.HAS_PYAES) = True, False, False 50 func(*args, **kwargs) # cryptodome 51 if has_cryptography: 52 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY, crypto.HAS_PYAES) = False, True, False 53 func(*args, **kwargs) # cryptography 54 finally: 55 crypto.HAS_CRYPTODOME = has_cryptodome 56 crypto.HAS_CRYPTOGRAPHY = has_cryptography 57 crypto.HAS_PYAES = has_pyaes 58 return run_test 59 60 61 def needs_test_with_all_chacha20_implementations(func): 62 """Function decorator to run a unit test multiple times: 63 once with each ChaCha20/Poly1305 implementation. 64 65 NOTE: this is inherently sequential; 66 tests running in parallel would break things 67 """ 68 def run_test(*args, **kwargs): 69 if FAST_TESTS: # if set, only run tests once, using fastest implementation 70 func(*args, **kwargs) 71 return 72 has_cryptodome = crypto.HAS_CRYPTODOME 73 has_cryptography = crypto.HAS_CRYPTOGRAPHY 74 try: 75 if has_cryptodome: 76 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY) = True, False 77 func(*args, **kwargs) # cryptodome 78 if has_cryptography: 79 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY) = False, True 80 func(*args, **kwargs) # cryptography 81 finally: 82 crypto.HAS_CRYPTODOME = has_cryptodome 83 crypto.HAS_CRYPTOGRAPHY = has_cryptography 84 return run_test 85 86 87 class Test_bitcoin(ElectrumTestCase): 88 89 def test_libsecp256k1_is_available(self): 90 # we want the unit testing framework to test with libsecp256k1 available. 91 self.assertTrue(bool(ecc_fast._libsecp256k1)) 92 93 def test_pycryptodomex_is_available(self): 94 # we want the unit testing framework to test with pycryptodomex available. 95 self.assertTrue(bool(crypto.HAS_CRYPTODOME)) 96 97 def test_cryptography_is_available(self): 98 # we want the unit testing framework to test with cryptography available. 99 self.assertTrue(bool(crypto.HAS_CRYPTOGRAPHY)) 100 101 def test_pyaes_is_available(self): 102 # we want the unit testing framework to test with pyaes available. 103 self.assertTrue(bool(crypto.HAS_PYAES)) 104 105 @needs_test_with_all_aes_implementations 106 def test_crypto(self): 107 for message in [b"Chancellor on brink of second bailout for banks", b'\xff'*512]: 108 self._do_test_crypto(message) 109 110 def _do_test_crypto(self, message): 111 G = ecc.GENERATOR 112 _r = G.order() 113 pvk = randrange(_r) 114 115 Pub = pvk*G 116 pubkey_c = Pub.get_public_key_bytes(True) 117 #pubkey_u = point_to_ser(Pub,False) 118 addr_c = public_key_to_p2pkh(pubkey_c) 119 120 #print "Private key ", '%064x'%pvk 121 eck = ecc.ECPrivkey.from_secret_scalar(pvk) 122 123 #print "Compressed public key ", pubkey_c.encode('hex') 124 enc = ecc.ECPubkey(pubkey_c).encrypt_message(message) 125 dec = eck.decrypt_message(enc) 126 self.assertEqual(message, dec) 127 128 #print "Uncompressed public key", pubkey_u.encode('hex') 129 #enc2 = EC_KEY.encrypt_message(message, pubkey_u) 130 dec2 = eck.decrypt_message(enc) 131 self.assertEqual(message, dec2) 132 133 signature = eck.sign_message(message, True) 134 #print signature 135 eck.verify_message_for_address(signature, message) 136 137 def test_ecc_sanity(self): 138 G = ecc.GENERATOR 139 n = G.order() 140 self.assertEqual(ecc.CURVE_ORDER, n) 141 inf = n * G 142 self.assertEqual(ecc.POINT_AT_INFINITY, inf) 143 self.assertTrue(inf.is_at_infinity()) 144 self.assertFalse(G.is_at_infinity()) 145 self.assertEqual(11 * G, 7 * G + 4 * G) 146 self.assertEqual((n + 2) * G, 2 * G) 147 self.assertEqual((n - 2) * G, -2 * G) 148 A = (n - 2) * G 149 B = (n - 1) * G 150 C = n * G 151 D = (n + 1) * G 152 self.assertFalse(A.is_at_infinity()) 153 self.assertFalse(B.is_at_infinity()) 154 self.assertTrue(C.is_at_infinity()) 155 self.assertTrue((C * 5).is_at_infinity()) 156 self.assertFalse(D.is_at_infinity()) 157 self.assertEqual(inf, C) 158 self.assertEqual(inf, A + 2 * G) 159 self.assertEqual(inf, D + (-1) * G) 160 self.assertNotEqual(A, B) 161 self.assertEqual(2 * G, inf + 2 * G) 162 self.assertEqual(inf, 3 * G + (-3 * G)) 163 164 def test_msg_signing(self): 165 msg1 = b'Chancellor on brink of second bailout for banks' 166 msg2 = b'Electrum' 167 168 def sign_message_with_wif_privkey(wif_privkey, msg): 169 txin_type, privkey, compressed = deserialize_privkey(wif_privkey) 170 key = ecc.ECPrivkey(privkey) 171 return key.sign_message(msg, compressed) 172 173 sig1 = sign_message_with_wif_privkey( 174 'L1TnU2zbNaAqMoVh65Cyvmcjzbrj41Gs9iTLcWbpJCMynXuap6UN', msg1) 175 addr1 = '15hETetDmcXm1mM4sEf7U2KXC9hDHFMSzz' 176 sig2 = sign_message_with_wif_privkey( 177 '5Hxn5C4SQuiV6e62A1MtZmbSeQyrLFhu5uYks62pU5VBUygK2KD', msg2) 178 addr2 = '1GPHVTY8UD9my6jyP4tb2TYJwUbDetyNC6' 179 180 sig1_b64 = base64.b64encode(sig1) 181 sig2_b64 = base64.b64encode(sig2) 182 183 self.assertEqual(sig1_b64, b'Hzsu0U/THAsPz/MSuXGBKSULz2dTfmrg1NsAhFp+wH5aKfmX4Db7ExLGa7FGn0m6Mf43KsbEOWpvUUUBTM3Uusw=') 184 self.assertEqual(sig2_b64, b'HBQdYfv7kOrxmRewLJnG7sV6KlU71O04hUnE4tai97p7Pg+D+yKaWXsdGgHTrKw90caQMo/D6b//qX50ge9P9iI=') 185 186 self.assertTrue(ecc.verify_message_with_address(addr1, sig1, msg1)) 187 self.assertTrue(ecc.verify_message_with_address(addr2, sig2, msg2)) 188 189 self.assertFalse(ecc.verify_message_with_address(addr1, b'wrong', msg1)) 190 self.assertFalse(ecc.verify_message_with_address(addr1, sig2, msg1)) 191 192 @needs_test_with_all_aes_implementations 193 def test_decrypt_message(self): 194 key = WalletStorage.get_eckey_from_password('pw123') 195 self.assertEqual(b'me<(s_s)>age', key.decrypt_message(b'QklFMQMDFtgT3zWSQsa+Uie8H/WvfUjlu9UN9OJtTt3KlgKeSTi6SQfuhcg1uIz9hp3WIUOFGTLr4RNQBdjPNqzXwhkcPi2Xsbiw6UCNJncVPJ6QBg==')) 196 self.assertEqual(b'me<(s_s)>age', key.decrypt_message(b'QklFMQKXOXbylOQTSMGfo4MFRwivAxeEEkewWQrpdYTzjPhqjHcGBJwdIhB7DyRfRQihuXx1y0ZLLv7XxLzrILzkl/H4YUtZB4uWjuOAcmxQH4i/Og==')) parazyd.org:70 /git/electrum/file/electrum/tests/test_bitcoin.py.gph:206: line too long