def test_sec(self): pair_blob = h2b("0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483a" "da7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8") sec_to_public_pair(pair_blob, secp256k1_generator, strict=False) try: sec_to_public_pair(pair_blob, secp256k1_generator, strict=True) self.fail("sec_to_public_pair unexpectedly succeeded") except EncodingError: pass
def test_sec(self): pair_blob = h2b( "0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483a" "da7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8") sec_to_public_pair(pair_blob, secp256k1_generator, strict=False) try: sec_to_public_pair(pair_blob, secp256k1_generator, strict=True) self.fail("sec_to_public_pair unexpectedly succeeded") except EncodingError: pass
def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58, c_address_b58): secret_exponent = int(exp_hex, 16) sec = h2b(public_pair_sec) c_sec = h2b(c_public_pair_sec) self.assertEqual( secret_exponent_to_wif(secret_exponent, compressed=False), wif) self.assertEqual( secret_exponent_to_wif(secret_exponent, compressed=True), c_wif) key = BitcoinMainnet.ui.parse(wif) exponent = key.secret_exponent() compressed = not key._use_uncompressed() self.assertEqual(exponent, secret_exponent) self.assertFalse(compressed) key = BitcoinMainnet.ui.parse(c_wif) exponent = key.secret_exponent() compressed = not key._use_uncompressed() self.assertEqual(exponent, secret_exponent) self.assertTrue(compressed) public_pair = secret_exponent * secp256k1_generator pk_public_pair = sec_to_public_pair(sec, secp256k1_generator) compressed = is_sec_compressed(sec) self.assertEqual(pk_public_pair, public_pair) self.assertFalse(is_sec_compressed(sec)) self.assertEqual( public_pair_to_sec(pk_public_pair, compressed=False), sec) pk_public_pair = sec_to_public_pair(c_sec, secp256k1_generator) compressed = is_sec_compressed(c_sec) self.assertEqual(pk_public_pair, public_pair) self.assertTrue(compressed) self.assertEqual( public_pair_to_sec(pk_public_pair, compressed=True), c_sec) bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=True) self.assertEqual(bca, c_address_b58) self.assertEqual( bitcoin_address_to_hash160_sec(c_address_b58), public_pair_to_hash160_sec(pk_public_pair, compressed=True)) bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=False) self.assertEqual(bca, address_b58) self.assertEqual( bitcoin_address_to_hash160_sec(address_b58), public_pair_to_hash160_sec(pk_public_pair, compressed=False))
def info_for_sec(self, prefix, text): sec = h2b(text) public_pair = sec_to_public_pair(sec, self._generator) is_compressed = is_sec_compressed(sec) kwargs = dict(public_pair=public_pair, is_compressed=is_compressed) return dict(type="key", key_type="sec", is_private=False, kwargs=kwargs, key_class=self._key_class, create_f=lambda: self._key_class(**kwargs))
def from_sec(class_, sec, generator=None): """ Create a key from an sec bytestream (which is an encoding of a public pair). """ generator = generator or class_._default_generator public_pair = sec_to_public_pair(sec, generator) return class_(public_pair=public_pair, is_compressed=is_sec_compressed(sec))
def from_sec(class_, sec, generator): """ Create a key from an sec bytestream (which is an encoding of a public pair). """ public_pair = sec_to_public_pair(sec, generator) return class_(public_pair=public_pair, is_compressed=is_sec_compressed(sec))
def f(solved_values, **kwargs): signature_type = kwargs.get("signature_type", DEFAULT_SIGNATURE_TYPE) generator_for_signature_type_f = kwargs[ "generator_for_signature_type_f"] signature_for_hash_type_f = m["signature_for_hash_type_f"] existing_script = kwargs.get("existing_script", b'') existing_signatures, secs_solved = _find_signatures( existing_script, generator_for_signature_type_f, signature_for_hash_type_f, len(m["sig_list"]), m["sec_list"]) sec_keys = m["sec_list"] signature_variables = m["sig_list"] signature_placeholder = kwargs.get("signature_placeholder", DEFAULT_PLACEHOLDER_SIGNATURE) db = kwargs.get("hash160_lookup", {}) # we reverse this enumeration to make the behaviour look like the old signer. BRAIN DAMAGE for signature_order, sec_key in reversed(list(enumerate(sec_keys))): sec_key = solved_values.get(sec_key, sec_key) if sec_key in secs_solved: continue if len(existing_signatures) >= len(signature_variables): break result = db.get(hash160(sec_key)) if result: secret_exponent = result[0] sig_hash = signature_for_hash_type_f(signature_type) generator = result[3] r, s = generator.sign(secret_exponent, sig_hash) else: # try existing signatures generator = generator_for_signature_type_f(signature_type) public_pair = sec_to_public_pair(sec_key, generator=generator) for sig in all_signature_hints(public_pair, signature_for_hash_type_f, **kwargs): sig_hash = signature_for_hash_type_f(indexbytes(sig, -1)) sig_pair = der.sigdecode_der(sig[:-1]) if generator.verify(public_pair, sig_hash, sig_pair): r, s = sig_pair break else: continue order = generator.order() if s + s > order: s = order - s binary_signature = der.sigencode_der(r, s) + int2byte(signature_type) existing_signatures.append((signature_order, binary_signature)) # pad with placeholder signatures if signature_placeholder is not None: while len(existing_signatures) < len(signature_variables): existing_signatures.append((-1, signature_placeholder)) existing_signatures.sort() return dict( zip(signature_variables, (es[-1] for es in existing_signatures)))
def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58, c_address_b58): secret_exponent = int(exp_hex, 16) sec = h2b(public_pair_sec) c_sec = h2b(c_public_pair_sec) self.assertEqual(secret_exponent_to_wif(secret_exponent, compressed=False), wif) self.assertEqual(secret_exponent_to_wif(secret_exponent, compressed=True), c_wif) key = network.parse.wif(wif) exponent = key.secret_exponent() compressed = key.is_compressed() self.assertEqual(exponent, secret_exponent) self.assertFalse(compressed) key = network.parse.wif(c_wif) exponent = key.secret_exponent() compressed = key.is_compressed() self.assertEqual(exponent, secret_exponent) self.assertTrue(compressed) public_pair = secret_exponent * key._generator pk_public_pair = sec_to_public_pair(sec, key._generator) compressed = is_sec_compressed(sec) self.assertEqual(pk_public_pair, public_pair) self.assertFalse(is_sec_compressed(sec)) self.assertEqual(public_pair_to_sec(pk_public_pair, compressed=False), sec) pk_public_pair = sec_to_public_pair(c_sec, key._generator) compressed = is_sec_compressed(c_sec) self.assertEqual(pk_public_pair, public_pair) self.assertTrue(compressed) self.assertEqual(public_pair_to_sec(pk_public_pair, compressed=True), c_sec) bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=True) self.assertEqual(bca, c_address_b58) self.assertEqual(bitcoin_address_to_hash160_sec(c_address_b58), public_pair_to_hash160_sec(pk_public_pair, compressed=True)) bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=False) self.assertEqual(bca, address_b58) self.assertEqual(bitcoin_address_to_hash160_sec(address_b58), public_pair_to_hash160_sec(pk_public_pair, compressed=False))
def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address): self.assertEqual(sec_to_public_pair(as_sec, secp256k1_generator), as_public_pair) self.assertEqual(public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec) self.assertEqual(is_sec_compressed(as_sec), is_compressed) self.assertEqual(public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed), as_hash160_sec) self.assertEqual(BitcoinMainnet.ui.address_for_p2pkh(as_hash160_sec), as_bitcoin_address) self.assertTrue(is_address_valid(as_bitcoin_address)) bad_address = as_bitcoin_address[:17] + chr(ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:] self.assertFalse(is_address_valid(bad_address))
def f(solved_values, **kwargs): signature_type = kwargs.get("signature_type", DEFAULT_SIGNATURE_TYPE) signature_hints = kwargs.get("signature_hints", []) generator_for_signature_type_f = kwargs["generator_for_signature_type_f"] signature_for_hash_type_f = m["signature_for_hash_type_f"] existing_script = kwargs.get("existing_script", b'') existing_signatures, secs_solved = _find_signatures( existing_script, generator_for_signature_type_f, signature_for_hash_type_f, len(m["sig_list"]), m["sec_list"]) sec_keys = m["sec_list"] signature_variables = m["sig_list"] signature_placeholder = kwargs.get("signature_placeholder", DEFAULT_PLACEHOLDER_SIGNATURE) db = kwargs.get("hash160_lookup", {}) # we reverse this enumeration to make the behaviour look like the old signer. BRAIN DAMAGE for signature_order, sec_key in reversed(list(enumerate(sec_keys))): sec_key = solved_values.get(sec_key, sec_key) if sec_key in secs_solved: continue if len(existing_signatures) >= len(signature_variables): break result = db.get(hash160(sec_key)) if result: secret_exponent = result[0] sig_hash = signature_for_hash_type_f(signature_type) generator = result[3] r, s = generator.sign(secret_exponent, sig_hash) else: # try existing signatures for sig in signature_hints: sig_hash = signature_for_hash_type_f(indexbytes(sig, -1)) generator = generator_for_signature_type_f(signature_type) public_pair = sec_to_public_pair(sec_key, generator=generator) sig_pair = der.sigdecode_der(sig[:-1]) if generator.verify(public_pair, sig_hash, sig_pair): r, s = sig_pair break else: continue order = generator.order() if s + s > order: s = order - s binary_signature = der.sigencode_der(r, s) + int2byte(signature_type) existing_signatures.append((signature_order, binary_signature)) # pad with placeholder signatures if signature_placeholder is not None: while len(existing_signatures) < len(signature_variables): existing_signatures.append((-1, signature_placeholder)) existing_signatures.sort() return dict(zip(signature_variables, (es[-1] for es in existing_signatures)))
def info_for_data(self, data, is_private): parent_fingerprint, child_index = struct.unpack(">4sL", data[5:13]) d = dict(generator=self._generator, chain_code=data[13:45], depth=ord(data[4:5]), parent_fingerprint=parent_fingerprint, child_index=child_index) if is_private: if data[45:46] != b'\0': return None d["secret_exponent"] = from_bytes_32(data[46:]) else: d["public_pair"] = sec_to_public_pair(data[45:], self._generator) return dict(type="key", key_type="bip32", bip32_type="plain", is_private=is_private, kwargs=d, key_class=self._bip32node_class, create_f=lambda: self._bip32node_class(**d))
def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address): self.assertEqual(sec_to_public_pair(as_sec, secp256k1_generator), as_public_pair) self.assertEqual( public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec) self.assertEqual(is_sec_compressed(as_sec), is_compressed) self.assertEqual( public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed), as_hash160_sec) self.assertEqual(network.address.for_p2pkh(as_hash160_sec), as_bitcoin_address) self.assertIsNotNone(network.parse.address(as_bitcoin_address)) bad_address = as_bitcoin_address[:17] + chr( ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:] self.assertIsNone(network.parse.address(bad_address))
def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address): self.assertEqual(sec_to_public_pair(as_sec, secp256k1_generator), as_public_pair) self.assertEqual( public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec) self.assertEqual(is_sec_compressed(as_sec), is_compressed) self.assertEqual( public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed), as_hash160_sec) self.assertEqual( BitcoinMainnet.ui.address_for_p2pkh(as_hash160_sec), as_bitcoin_address) self.assertTrue(is_address_valid(as_bitcoin_address)) bad_address = as_bitcoin_address[:17] + chr( ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:] self.assertFalse(is_address_valid(bad_address))
def _find_signatures(script_blobs, generator_for_signature_type_f, signature_for_hash_type_f, max_sigs, sec_keys): signatures = [] secs_solved = set() seen = 0 for data in script_blobs: if seen >= max_sigs: break try: sig_pair, signature_type = parse_signature_blob(data) generator = generator_for_signature_type_f(signature_type) seen += 1 for idx, sec_key in enumerate(sec_keys): public_pair = sec_to_public_pair(sec_key, generator) sign_value = signature_for_hash_type_f(signature_type) v = generator.verify(public_pair, sign_value, sig_pair) if v: signatures.append((idx, data)) secs_solved.add(sec_key) break except (ValueError, EncodingError, der.UnexpectedDER, ScriptError): # if public_pair is invalid, we just ignore it pass return signatures, secs_solved