You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

57 lines
2.4 KiB

#! /usr/bin/env python
'''Tests coincurve binding to libsecp256k1 ecdh module code'''
import hashlib
import jmbitcoin as btc
from jmbase import hextobin
import pytest
import os
import json
testdir = os.path.dirname(os.path.realpath(__file__))
def test_ecdh():
"""Using private key test vectors from Bitcoin Core.
1. Import a set of private keys from the json file.
2. Calculate the corresponding public keys.
3. Do ECDH on the cartesian product (x, Y), with x private
and Y public keys, for all combinations.
4. Compare the result from CoinCurve with the manual
multiplication xY following by hash (sha256). Note that
sha256(xY) is the default hashing function used for ECDH
in libsecp256k1.
Since there are about 20 private keys in the json file, this
creates around 400 test cases (note xX is still valid).
"""
with open(os.path.join(testdir,"base58_keys_valid.json"), "r") as f:
json_data = f.read()
valid_keys_list = json.loads(json_data)
extracted_privkeys = []
for a in valid_keys_list:
key, hex_key, prop_dict = a
if prop_dict["isPrivkey"]:
c, k = btc.read_privkey(hextobin(hex_key))
extracted_privkeys.append(k)
extracted_pubkeys = [btc.privkey_to_pubkey(x) for x in extracted_privkeys]
for p in extracted_privkeys:
for P in extracted_pubkeys:
c, k = btc.read_privkey(p)
shared_secret = btc.ecdh(k, P)
assert len(shared_secret) == 32
# try recreating the shared secret manually:
pre_secret = btc.multiply(p, P)
derived_secret = hashlib.sha256(pre_secret).digest()
assert derived_secret == shared_secret
# test some important failure cases; null key, overflow case
privkeys_invalid = [b'\x00'*32, hextobin(
'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141')]
for p in privkeys_invalid:
with pytest.raises(Exception) as e_info:
shared_secret = btc.ecdh(p, extracted_pubkeys[0])
pubkeys_invalid = [b'0xff' + extracted_pubkeys[0][1:], b'0x00'*12]
for p in extracted_privkeys:
with pytest.raises(Exception) as e_info:
shared_secret = btc.ecdh(p, pubkeys_invalid[0])
with pytest.raises(Exception) as e_info:
shared_secret = btc.ecdh(p, pubkeys_invalid[1])