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