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