|
@@ -0,0 +1,84 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+
|
|
|
+"""
|
|
|
+test.unit_tests_d.ut_ecc: elliptic curve unit test for the MMGen suite
|
|
|
+"""
|
|
|
+
|
|
|
+from mmgen.color import gray,pink,blue
|
|
|
+from mmgen.proto.secp256k1.secp256k1 import pubkey_gen,pubkey_tweak_add,pubkey_check
|
|
|
+
|
|
|
+from ..include.common import cfg,qmsg,vmsg
|
|
|
+from ..include.ecc import pubkey_tweak_add_py_ecdsa
|
|
|
+from mmgen.protocol import CoinProtocol
|
|
|
+
|
|
|
+secp256k1_group_order = CoinProtocol.Secp256k1.secp256k1_group_order
|
|
|
+
|
|
|
+class unit_tests:
|
|
|
+
|
|
|
+ def pubkey_ops(self,name,ut):
|
|
|
+ vmsg(f' Generating pubkey, adding scalar 123456789 to pubkey:')
|
|
|
+ pk_addend_bytes = int.to_bytes(123456789,length=32)
|
|
|
+
|
|
|
+ for privkey in (
|
|
|
+ 'beadcafe' * 8,
|
|
|
+ f'{1:064x}',
|
|
|
+ f'{secp256k1_group_order-1:x}',
|
|
|
+ ):
|
|
|
+ vmsg(f' privkey = 0x{privkey}')
|
|
|
+ for compressed,length in ((False,65),(True,33)):
|
|
|
+ vmsg(f' {compressed=}')
|
|
|
+ pubkey_bytes = pubkey_gen(bytes.fromhex(privkey),int(compressed))
|
|
|
+ pubkey_check(pubkey_bytes)
|
|
|
+ vmsg(f' pubkey: {pubkey_bytes.hex()}')
|
|
|
+
|
|
|
+ res1 = pubkey_tweak_add(pubkey_bytes, pk_addend_bytes)
|
|
|
+ pubkey_check(res1)
|
|
|
+ vmsg(f' tweaked: {res1.hex()}')
|
|
|
+
|
|
|
+ res2 = pubkey_tweak_add_py_ecdsa(pubkey_bytes,pk_addend_bytes)
|
|
|
+ pubkey_check(res2)
|
|
|
+
|
|
|
+ assert len(res1) == length
|
|
|
+ assert res1 == res2
|
|
|
+
|
|
|
+ return True
|
|
|
+
|
|
|
+ def pubkey_errors(self,name,ut):
|
|
|
+
|
|
|
+ def gen1(): pubkey_gen(bytes(32),1)
|
|
|
+ def gen2(): pubkey_gen(secp256k1_group_order.to_bytes(length=32),1)
|
|
|
+ def gen3(): pubkey_gen((secp256k1_group_order+1).to_bytes(length=32),1)
|
|
|
+ def gen4(): pubkey_gen(bytes.fromhex('ff'*32),1)
|
|
|
+ def gen5(): pubkey_gen(bytes.fromhex('ab'*31),1)
|
|
|
+ def gen6(): pubkey_gen(bytes.fromhex('ab'*33),1)
|
|
|
+
|
|
|
+ pubkey_bytes = pubkey_gen(bytes.fromhex('beadcafe'*8), 1)
|
|
|
+ def tweak1(): pubkey_tweak_add(pubkey_bytes,bytes(32))
|
|
|
+ def tweak2(): pubkey_tweak_add(bytes.fromhex('03'*64),int.to_bytes(1,length=32))
|
|
|
+
|
|
|
+ def check1(): pubkey_check(bytes.fromhex('04'*33))
|
|
|
+ def check2(): pubkey_check(bytes.fromhex('03'*65))
|
|
|
+ def check3(): pubkey_check(bytes.fromhex('02'*65))
|
|
|
+ def check4(): pubkey_check(bytes.fromhex('03'*64))
|
|
|
+ def check5(): pubkey_check(b'')
|
|
|
+
|
|
|
+ bad_data = (
|
|
|
+ ('privkey == 0', 'ValueError', 'Private key not in allowable range', gen1),
|
|
|
+ ('privkey == group order', 'ValueError', 'Private key not in allowable range', gen2),
|
|
|
+ ('privkey == group order+1', 'ValueError', 'Private key not in allowable range', gen3),
|
|
|
+ ('privkey == 2^256-1', 'ValueError', 'Private key not in allowable range', gen4),
|
|
|
+ ('len(privkey) == 31', 'ValueError', 'Private key length not 32 bytes', gen5),
|
|
|
+ ('len(privkey) == 33', 'ValueError', 'Private key length not 32 bytes', gen6),
|
|
|
+
|
|
|
+ ('tweak == 0', 'ValueError', 'Tweak not in allowable range', tweak1),
|
|
|
+ ('pubkey length == 64', 'ValueError', 'Serialized public key length not', tweak2),
|
|
|
+
|
|
|
+ ('invalid pubkey (33 bytes)', 'ValueError', 'Invalid first byte', check1),
|
|
|
+ ('invalid pubkey (65 bytes)', 'ValueError', 'Invalid first byte', check2),
|
|
|
+ ('invalid pubkey (65 bytes)', 'ValueError', 'Invalid first byte', check3),
|
|
|
+ ('pubkey length == 64', 'ValueError', 'Serialized public key length not', check4),
|
|
|
+ ('pubkey length == 0', 'ValueError', 'Serialized public key length not', check5),
|
|
|
+ )
|
|
|
+
|
|
|
+ ut.process_bad_data(bad_data,pfx='')
|
|
|
+ return True
|