-
Notifications
You must be signed in to change notification settings - Fork 67
/
Copy pathtest_native_backend_against_coincurve.py
159 lines (129 loc) · 4.23 KB
/
test_native_backend_against_coincurve.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import pytest
from hypothesis import (
given,
settings,
strategies as st,
)
from eth_utils import (
int_to_big_endian,
keccak,
)
from eth_keys.exceptions import (
BadSignature,
)
from eth_keys.utils.padding import (
pad32,
)
from eth_keys import KeyAPI
from eth_keys.backends import CoinCurveECCBackend
from eth_keys.backends import NativeECCBackend
from eth_keys.constants import (
SECPK1_N,
)
private_key_st = st.integers(min_value=1, max_value=SECPK1_N).map(
int_to_big_endian,
).map(pad32)
message_hash_st = st.binary(min_size=32, max_size=32)
signature_st = st.binary(min_size=65, max_size=65)
MSG = b'message'
MSGHASH = keccak(MSG)
MAX_EXAMPLES = 200
@pytest.fixture
def native_key_api():
return KeyAPI(backend=NativeECCBackend())
@pytest.fixture
def coincurve_key_api():
return KeyAPI(backend=CoinCurveECCBackend())
@given(
private_key_bytes=private_key_st,
direction=st.one_of(
st.just('coincurve-to-native'),
st.just('native-to-coincurve'),
),
)
@settings(max_examples=MAX_EXAMPLES)
def test_public_key_generation_is_equal(private_key_bytes,
direction,
native_key_api,
coincurve_key_api):
if direction == 'coincurve-to-native':
backend_a = coincurve_key_api
backend_b = native_key_api
elif direction == 'native-to-coincurve':
backend_b = coincurve_key_api
backend_a = native_key_api
else:
assert False, "invariant"
public_key_a = backend_a.PrivateKey(private_key_bytes).public_key
public_key_b = backend_b.PrivateKey(private_key_bytes).public_key
assert public_key_a == public_key_b
@given(
private_key_bytes=private_key_st,
message_hash=message_hash_st,
direction=st.one_of(
st.just('coincurve-to-native'),
st.just('native-to-coincurve'),
),
)
@settings(max_examples=MAX_EXAMPLES)
def test_native_to_coincurve_recover(private_key_bytes,
message_hash,
direction,
native_key_api,
coincurve_key_api):
if direction == 'coincurve-to-native':
backend_a = coincurve_key_api
backend_b = native_key_api
elif direction == 'native-to-coincurve':
backend_b = coincurve_key_api
backend_a = native_key_api
else:
assert False, "invariant"
pk_a = backend_a.PrivateKey(private_key_bytes)
signature_a = backend_a.ecdsa_sign(message_hash, pk_a)
public_key_b = backend_b.ecdsa_recover(message_hash, signature_a)
assert public_key_b == pk_a.public_key
@given(
message_hash=message_hash_st,
signature_bytes=signature_st,
direction=st.one_of(
st.just('coincurve-to-native'),
st.just('native-to-coincurve'),
),
)
@settings(max_examples=MAX_EXAMPLES)
def test_coincurve_to_native_invalid_signatures(message_hash,
signature_bytes,
direction,
native_key_api,
coincurve_key_api):
if direction == 'coincurve-to-native':
backend_a = coincurve_key_api
backend_b = native_key_api
elif direction == 'native-to-coincurve':
backend_b = coincurve_key_api
backend_a = native_key_api
else:
assert False, "invariant"
try:
signature_a = backend_a.Signature(signature_bytes)
except BadSignature:
is_bad_signature = True
else:
is_bad_signature = False
if is_bad_signature:
with pytest.raises(BadSignature):
backend_b.Signature(signature_bytes)
return
try:
public_key_a = backend_a.ecdsa_recover(message_hash, signature_a)
except BadSignature:
is_bad_recovery = True
else:
is_bad_recovery = False
if is_bad_recovery:
with pytest.raises(BadSignature):
backend_b.ecdsa_recover(message_hash, signature_a)
return
public_key_b = backend_b.ecdsa_recover(message_hash, signature_a)
assert public_key_b == public_key_a