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 |