ethereum.crypto.elliptic_curve
Elliptic Curves.
SECP256K1B
17 | SECP256K1B = U256(7) |
---|
SECP256K1P
18 | SECP256K1P = U256( |
---|---|
19 | 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F |
20 | ) |
SECP256K1N
21 | SECP256K1N = U256( |
---|---|
22 | 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 |
23 | ) |
secp256k1_recover
Recovers the public key from a given signature.
Parameters
r : TODO s : TODO v : TODO msg_hash : Hash of the message being recovered.
Returns
public_key : ethereum.base_types.Bytes
Recovered public key.
def secp256k1_recover(r: U256, s: U256, v: U256, msg_hash: Hash32) -> Bytes:
27 | """ |
---|---|
28 | Recovers the public key from a given signature. |
29 |
|
30 | Parameters |
31 | ---------- |
32 | r : |
33 | TODO |
34 | s : |
35 | TODO |
36 | v : |
37 | TODO |
38 | msg_hash : |
39 | Hash of the message being recovered. |
40 |
|
41 | Returns |
42 | ------- |
43 | public_key : `ethereum.base_types.Bytes` |
44 | Recovered public key. |
45 |
|
46 | """ |
47 | is_square = pow( |
48 | pow(r, U256(3), SECP256K1P) + SECP256K1B, |
49 | (SECP256K1P - U256(1)) // U256(2), |
50 | SECP256K1P, |
51 | ) |
52 | |
53 | if is_square != 1: |
54 | raise InvalidSignatureError( |
55 | "r is not the x-coordinate of a point on the secp256k1 curve" |
56 | ) |
57 | |
58 | r_bytes = r.to_be_bytes32() |
59 | s_bytes = s.to_be_bytes32() |
60 | |
61 | signature = bytearray([0] * 65) |
62 | signature[32 - len(r_bytes) : 32] = r_bytes |
63 | signature[64 - len(s_bytes) : 64] = s_bytes |
64 | signature[64] = v |
65 | |
66 | # If the recovery algorithm returns the point at infinity, |
67 | # the signature is considered invalid |
68 | # the below function will raise a ValueError. |
69 | try: |
70 | public_key = coincurve.PublicKey.from_signature_and_message( |
71 | bytes(signature), msg_hash, hasher=None |
72 | ) |
73 | except ValueError as e: |
74 | raise InvalidSignatureError from e |
75 | |
76 | public_key = public_key.format(compressed=False)[1:] |
77 | return public_key |
SECP256R1N
80 | SECP256R1N = U256( |
---|---|
81 | 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 |
82 | ) |
SECP256R1P
83 | SECP256R1P = U256( |
---|---|
84 | 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF |
85 | ) |
SECP256R1A
86 | SECP256R1A = U256( |
---|---|
87 | 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC |
88 | ) |
SECP256R1B
89 | SECP256R1B = U256( |
---|---|
90 | 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B |
91 | ) |
secp256r1_verify
Verifies a P-256 signature.
Parameters
r :
the r
component of the signature
s :
the s
component of the signature
x :
the x
coordinate of the public key
y :
the y
coordinate of the public key
msg_hash :
Hash of the message being recovered.
Raises
Raises an InvalidSignatureError
if the signature is not valid.
def secp256r1_verify(r: U256, s: U256, x: U256, y: U256, msg_hash: Hash32) -> None:
97 | """ |
---|---|
98 | Verifies a P-256 signature. |
99 |
|
100 | Parameters |
101 | ---------- |
102 | r : |
103 | the `r` component of the signature |
104 | s : |
105 | the `s` component of the signature |
106 | x : |
107 | the `x` coordinate of the public key |
108 | y : |
109 | the `y` coordinate of the public key |
110 | msg_hash : |
111 | Hash of the message being recovered. |
112 |
|
113 | Raises |
114 | ------ |
115 | Raises an `InvalidSignatureError` if the signature is not valid. |
116 |
|
117 | """ |
118 | # Convert U256 to regular integers for DerSequence |
119 | r_int = int(r) |
120 | s_int = int(s) |
121 | x_int = int(x) |
122 | y_int = int(y) |
123 | |
124 | sig = DerSequence([r_int, s_int]).encode() |
125 | |
126 | pubnum = ec.EllipticCurvePublicNumbers(x_int, y_int, ec.SECP256R1()) |
127 | pubkey = pubnum.public_key(default_backend()) |
128 | |
129 | try: |
130 | pubkey.verify(sig, msg_hash, ec.ECDSA(Prehashed(hashes.SHA256()))) |
131 | except InvalidSignature as e: |
132 | raise InvalidSignatureError from e |
is_on_curve_secp256r1
Checks if a point is on the secp256r1 curve.
The point (x, y) must satisfy the curve equation: y^2 ≡ x^3 + a*x + b (mod p)
Parameters
x : U256 The x-coordinate of the point y : U256 The y-coordinate of the point
Returns
bool True if the point is on the curve, False otherwise
def is_on_curve_secp256r1(x: U256, y: U256) -> bool:
136 | """ |
---|---|
137 | Checks if a point is on the secp256r1 curve. |
138 |
|
139 | The point (x, y) must satisfy the curve equation: |
140 | y^2 ≡ x^3 + a*x + b (mod p) |
141 |
|
142 | Parameters |
143 | ---------- |
144 | x : U256 |
145 | The x-coordinate of the point |
146 | y : U256 |
147 | The y-coordinate of the point |
148 |
|
149 | Returns |
150 | ------- |
151 | bool |
152 | True if the point is on the curve, False otherwise |
153 |
|
154 | """ |
155 | # Convert U256 to int for calculations |
156 | x_int = int(x) |
157 | y_int = int(y) |
158 | p_int = int(SECP256R1P) |
159 | a_int = int(SECP256R1A) |
160 | b_int = int(SECP256R1B) |
161 | |
162 | # Calculate y^2 mod p |
163 | y_squared = (y_int * y_int) % p_int |
164 | |
165 | # Calculate x^3 + ax + b mod p |
166 | x_cubed = (x_int * x_int * x_int) % p_int |
167 | ax = (a_int * x_int) % p_int |
168 | right_side = (x_cubed + ax + b_int) % p_int |
169 | |
170 | return y_squared == right_side |