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