You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Create a new {@link ForeignCurve} from an object representing the (affine) x and y coordinates.
44
45
*
45
46
* Note: Inputs must be range checked if they originate from a different field with a different modulus or if they are not constants. Please refer to the {@link ForeignField} constructor comments for more details.
46
-
*
47
+
*
47
48
* @example
48
49
* ```ts
49
50
* let x = new ForeignCurve({ x: 1n, y: 1n });
@@ -74,6 +75,124 @@ class ForeignCurve {
74
75
returnnewthis(g);
75
76
}
76
77
78
+
/**
79
+
* Parses a hexadecimal string representing an uncompressed elliptic curve point and coerces it into a {@link ForeignCurveV2} point.
80
+
*
81
+
* The method extracts the x and y coordinates from the provided hex string and verifies that the resulting point lies on the curve.
82
+
*
83
+
* **Note:** This method only supports uncompressed elliptic curve points, which are 65 bytes in total (1-byte prefix + 32 bytes for x + 32 bytes for y).
84
+
*
85
+
* @param hex - The hexadecimal string representing the uncompressed elliptic curve point.
86
+
* @returns - A point on the foreign curve, parsed from the given hexadecimal string.
87
+
*
88
+
* @throws - Throws an error if the input is not a valid public key.
89
+
*
90
+
* @example
91
+
* ```ts
92
+
* class Secp256k1 extends createForeignCurveV2(Crypto.CurveParams.Secp256k1) {}
93
+
*
94
+
* const publicKeyHex = '04f8b8db25c619d0c66b2dc9e97ecbafafae...'; // Example hex string for uncompressed point
95
+
* const point = Secp256k1.fromHex(publicKeyHex);
96
+
* ```
97
+
*
98
+
* **Important:** This method is only designed to handle uncompressed elliptic curve points in hex format.
// extract x and y coordinates from the byte array
110
+
consttail=bytes.subarray(1);// skip the first byte (prefix)
111
+
constxBytes=tail.subarray(0,sizeInBytes);// first `sizeInBytes` bytes for x-coordinate
112
+
constyBytes=tail.subarray(sizeInBytes,2*sizeInBytes);// next `sizeInBytes` bytes for y-coordinate
113
+
114
+
// convert byte arrays to bigint
115
+
constx=BigInt('0x'+Bytes.from(xBytes).toHex());
116
+
consty=BigInt('0x'+Bytes.from(yBytes).toHex());
117
+
118
+
// construct the point on the curve using the x and y coordinates
119
+
letP=this.from({ x, y });
120
+
121
+
// ensure that the point is on the curve
122
+
P.assertOnCurve();
123
+
124
+
returnP;
125
+
}
126
+
127
+
/**
128
+
* Create a new {@link ForeignCurveV2} instance from an Ethereum public key in hex format, which may be either compressed or uncompressed.
129
+
* This method is designed to handle the parsing of public keys as used by the ethers.js library.
130
+
*
131
+
* The input should represent the affine x and y coordinates of the point, in hexadecimal format.
132
+
* Compressed keys are 33 bytes long and begin with 0x02 or 0x03, while uncompressed keys are 65 bytes long and begin with 0x04.
133
+
*
134
+
* **Warning:** This method is specifically designed for use with the Secp256k1 curve. Using it with other curves may result in incorrect behavior or errors.
135
+
* Ensure that the curve setup matches Secp256k1, as shown in the example, to avoid unintended issues.
136
+
*
137
+
* @example
138
+
* ```ts
139
+
* import { Wallet, Signature, getBytes } from 'ethers';
140
+
*
141
+
* class Secp256k1 extends createForeignCurveV2(Crypto.CurveParams.Secp256k1) {}
Copy file name to clipboardexpand all lines: src/lib/provable/crypto/foreign-ecdsa.ts
+53-1
Original file line number
Diff line number
Diff line change
@@ -38,7 +38,7 @@ class EcdsaSignature {
38
38
39
39
/**
40
40
* Create a new {@link EcdsaSignature} from an object containing the scalars r and s.
41
-
*
41
+
*
42
42
* Note: Inputs must be range checked if they originate from a different field with a different modulus or if they are not constants. Please refer to the {@link ForeignField} constructor comments for more details.
43
43
*/
44
44
constructor(signature: {
@@ -122,6 +122,58 @@ class EcdsaSignature {
122
122
returnthis.verifySignedHashV2(msgHash,publicKey);
123
123
}
124
124
125
+
/**
126
+
* Verify an ECDSA signature generated by the ethers.js library, given the message (as a byte array) and a public key (a {@link Curve} point).
127
+
* The message digest used for signing follows the format defined in EIP-191, with the Ethereum-specific prefix.
128
+
*
129
+
* **Important:** This method returns a {@link Bool} which indicates whether the signature is valid.
130
+
* So, to actually prove validity of a signature, you need to assert that the result is true.
131
+
*
132
+
* **Note:** This method is specifically designed to verify signatures generated by ethers.js.
133
+
* Ensure that the curve being used is Secp256k1, as demonstrated in the example.
134
+
*
135
+
* @throws An error will be thrown if one of the signature scalars is zero or if the public key does not lie on the curve.
136
+
*
137
+
* @example
138
+
* ```ts
139
+
* import { Wallet } from 'ethers';
140
+
*
141
+
* // create the class for Secp256k1 curve
142
+
* class Secp256k1 extends createForeignCurveV2(Crypto.CurveParams.Secp256k1) {}
143
+
* class Ecdsa extends createEcdsaV2(Secp256k1) {}
144
+
*
145
+
* // outside provable code: create inputs
146
+
* let message = 'my message';
147
+
* let signatureRaw = await wallet.signMessage(message);
148
+
* let compressedPublicKey = wallet.signingKey.compressedPublicKey;
149
+
*
150
+
* // this also works for uncompressed public keys (wallet.signingKey.publicKey)
151
+
* let publicKey = Secp256k1.fromEthers(compressedPublicKey.slice(2));
152
+
* let signature = Ecdsa.fromHex(signatureRaw);
153
+
*
154
+
* // ...
155
+
* // in provable code: create input witnesses (or use method inputs, or constants)
156
+
* // and verify the signature
157
+
* let isValid = signature.verifyEthers(Bytes.fromString(message), publicKey);
158
+
* isValid.assertTrue('signature verifies');
159
+
* ```
160
+
*
161
+
* @param message - The original message as a byte array.
162
+
* @param publicKey - The public key as a point on the Secp256k1 elliptic curve.
163
+
* @returns - A {@link Bool} indicating the validity of the signature.
0 commit comments