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
    <snip>
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
    <snip>
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
    <snip>
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