@pbnjam/bandersnatch 0.7.2-rc0 → 0.7.2-rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/docs.yml +0 -2
- package/LICENSE +3 -0
- package/package.json +6 -6
- package/src/curve.ts +44 -36
- package/src/index.ts +4 -4
- package/src/math.ts +12 -13
- package/src/types.ts +2 -3
package/LICENSE
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pbnjam/bandersnatch",
|
|
3
|
-
"version": "0.7.2-
|
|
3
|
+
"version": "0.7.2-rc2",
|
|
4
4
|
"description": "Bandersnatch elliptic curve implementation",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/Esscrypt/bandersnatch.git"
|
|
9
|
+
"url": "git+https://github.com/Esscrypt/bandersnatch.git"
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://github.com/Esscrypt/bandersnatch",
|
|
12
12
|
"bugs": {
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
"docs": "npx typedoc --out docs --entryPoints src/index.ts --entryPointStrategy expand --readme none --name '@pbnjam/bandersnatch' --includeVersion --tsconfig tsconfig.typedoc.json"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@noble/curves": "
|
|
23
|
-
"@noble/hashes": "
|
|
22
|
+
"@noble/curves": "2.0.1",
|
|
23
|
+
"@noble/hashes": "2.0.1"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@types/bun": "
|
|
26
|
+
"@types/bun": "1.3.5",
|
|
27
27
|
"@types/node": "^22.0.0",
|
|
28
|
-
"bun-types": "
|
|
28
|
+
"bun-types": "1.3.5",
|
|
29
29
|
"typescript": "5.9.3",
|
|
30
30
|
"typedoc": "0.28.15"
|
|
31
31
|
},
|
package/src/curve.ts
CHANGED
|
@@ -43,12 +43,12 @@ export const Bandersnatch = edwards(BANDERSNATCH_CURVE)
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Bandersnatch curve operations using @noble/curves.
|
|
46
|
-
*
|
|
46
|
+
*
|
|
47
47
|
* This class provides a high-level interface for working with points on the
|
|
48
48
|
* Bandersnatch elliptic curve. It implements all standard elliptic curve operations
|
|
49
49
|
* including point addition, scalar multiplication, and point compression/decompression
|
|
50
50
|
* compatible with arkworks serialization format.
|
|
51
|
-
*
|
|
51
|
+
*
|
|
52
52
|
* The Bandersnatch curve is a Twisted Edwards curve defined over the BLS12-381 scalar field,
|
|
53
53
|
* designed for efficient cryptographic operations in the JAM protocol.
|
|
54
54
|
*/
|
|
@@ -92,22 +92,28 @@ export class BandersnatchCurve {
|
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* Decompresses arkworks-compatible point bytes to a Noble EdwardsPoint.
|
|
95
|
-
*
|
|
95
|
+
*
|
|
96
96
|
* This is the inverse operation of `pointToBytes`. It handles arkworks sign bit logic
|
|
97
97
|
* to reconstruct the full point from compressed bytes. The method:
|
|
98
98
|
* 1. Extracts the y-coordinate from the first 31 bytes (little-endian)
|
|
99
99
|
* 2. Extracts the x-coordinate sign from bit 7 of the last byte
|
|
100
100
|
* 3. Computes the x-coordinate from y using the curve equation
|
|
101
|
-
* 4.
|
|
101
|
+
* 4. Optionally validates the point is in the prime subgroup G
|
|
102
102
|
*
|
|
103
103
|
* @param bytes - Compressed point bytes in arkworks format (32 bytes)
|
|
104
|
+
* @param validateSubgroup - Whether to validate point is in prime subgroup (default: true)
|
|
105
|
+
* Set to false for faster validation when only checking if bytes
|
|
106
|
+
* represent a valid curve point (e.g., for padding point replacement)
|
|
104
107
|
* @returns Decompressed Noble EdwardsPoint
|
|
105
108
|
* @throws {Error} If the byte array length is not 32
|
|
106
109
|
* @throws {Error} If the y-coordinate exceeds the field modulus
|
|
107
110
|
* @throws {Error} If the point is not on the curve (no square root exists)
|
|
108
|
-
* @throws {Error} If
|
|
111
|
+
* @throws {Error} If validatePointOnCurve is true and point is not on the curve
|
|
109
112
|
*/
|
|
110
|
-
static bytesToPoint(
|
|
113
|
+
static bytesToPoint(
|
|
114
|
+
bytes: Uint8Array,
|
|
115
|
+
validatePointOnCurve = true,
|
|
116
|
+
): EdwardsPoint {
|
|
111
117
|
if (bytes.length !== 32) {
|
|
112
118
|
throw new Error(
|
|
113
119
|
`Invalid compressed point length: ${bytes.length}, expected 32`,
|
|
@@ -167,25 +173,27 @@ export class BandersnatchCurve {
|
|
|
167
173
|
// Create Noble point from affine coordinates
|
|
168
174
|
const point = Bandersnatch.fromAffine({ x: finalX, y })
|
|
169
175
|
|
|
170
|
-
//
|
|
176
|
+
// Optionally validate point is in prime subgroup as required by bandersnatch-vrf-spec section 2.1:
|
|
171
177
|
// "This function MUST outputs 'INVALID' if the octet-string does not decode
|
|
172
178
|
// to a point on the prime subgroup G"
|
|
173
179
|
// A point is in the prime subgroup if and only if multiplying by the curve order
|
|
174
180
|
// gives the identity point (infinity)
|
|
175
181
|
// Since @noble/curves requires 1 <= scalar < curve.n, we use CURVE_ORDER - 1
|
|
176
182
|
// and then add the point once more: point * CURVE_ORDER = point * (CURVE_ORDER - 1) + point
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const pointTimesOrder = this.add(pointTimesOrderMinusOne, point)
|
|
183
|
-
const isInPrimeSubgroup = pointTimesOrder.equals(Bandersnatch.ZERO)
|
|
184
|
-
|
|
185
|
-
if (!isInPrimeSubgroup) {
|
|
186
|
-
throw new Error(
|
|
187
|
-
'Point is not in prime subgroup: decoded point is not in G',
|
|
183
|
+
if (validatePointOnCurve) {
|
|
184
|
+
const curveOrderMinusOne = BANDERSNATCH_PARAMS.CURVE_ORDER - 1n
|
|
185
|
+
const pointTimesOrderMinusOne = this.scalarMultiply(
|
|
186
|
+
point,
|
|
187
|
+
curveOrderMinusOne,
|
|
188
188
|
)
|
|
189
|
+
const pointTimesOrder = this.add(pointTimesOrderMinusOne, point)
|
|
190
|
+
const isInPrimeSubgroup = pointTimesOrder.equals(Bandersnatch.ZERO)
|
|
191
|
+
|
|
192
|
+
if (!isInPrimeSubgroup) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
'Point is not in prime subgroup: decoded point is not in G',
|
|
195
|
+
)
|
|
196
|
+
}
|
|
189
197
|
}
|
|
190
198
|
|
|
191
199
|
return point
|
|
@@ -193,12 +201,12 @@ export class BandersnatchCurve {
|
|
|
193
201
|
|
|
194
202
|
/**
|
|
195
203
|
* Performs scalar multiplication on a curve point.
|
|
196
|
-
*
|
|
204
|
+
*
|
|
197
205
|
* Computes `scalar * point` on the Bandersnatch curve. Handles edge cases including:
|
|
198
206
|
* - Scalar 0: returns the identity point (infinity)
|
|
199
207
|
* - Negative scalars: negates the point and uses positive scalar
|
|
200
208
|
* - Scalars >= curve order: reduces modulo curve order
|
|
201
|
-
*
|
|
209
|
+
*
|
|
202
210
|
* @param point - The curve point to multiply
|
|
203
211
|
* @param scalar - The scalar multiplier (can be negative or >= curve order)
|
|
204
212
|
* @returns The result of scalar multiplication: `scalar * point`
|
|
@@ -234,10 +242,10 @@ export class BandersnatchCurve {
|
|
|
234
242
|
|
|
235
243
|
/**
|
|
236
244
|
* Adds two curve points together.
|
|
237
|
-
*
|
|
245
|
+
*
|
|
238
246
|
* Performs point addition on the Bandersnatch curve: `P + Q`.
|
|
239
247
|
* This operation is commutative: `add(P, Q) === add(Q, P)`.
|
|
240
|
-
*
|
|
248
|
+
*
|
|
241
249
|
* @param p1 - First curve point
|
|
242
250
|
* @param p2 - Second curve point
|
|
243
251
|
* @returns The sum of the two points: `p1 + p2`
|
|
@@ -249,10 +257,10 @@ export class BandersnatchCurve {
|
|
|
249
257
|
|
|
250
258
|
/**
|
|
251
259
|
* Doubles a curve point.
|
|
252
|
-
*
|
|
260
|
+
*
|
|
253
261
|
* Computes `2 * point` on the Bandersnatch curve. This is equivalent to
|
|
254
262
|
* `add(point, point)` but is typically more efficient.
|
|
255
|
-
*
|
|
263
|
+
*
|
|
256
264
|
* @param point - The curve point to double
|
|
257
265
|
* @returns The doubled point: `2 * point`
|
|
258
266
|
* @throws {Error} If the point is invalid or not on the curve
|
|
@@ -263,10 +271,10 @@ export class BandersnatchCurve {
|
|
|
263
271
|
|
|
264
272
|
/**
|
|
265
273
|
* Negates a curve point.
|
|
266
|
-
*
|
|
274
|
+
*
|
|
267
275
|
* Computes the additive inverse of a point on the Bandersnatch curve.
|
|
268
276
|
* The result satisfies: `add(point, negate(point)) === INFINITY`.
|
|
269
|
-
*
|
|
277
|
+
*
|
|
270
278
|
* @param point - The curve point to negate
|
|
271
279
|
* @returns The negated point: `-point`
|
|
272
280
|
* @throws {Error} If the point is invalid or not on the curve
|
|
@@ -277,10 +285,10 @@ export class BandersnatchCurve {
|
|
|
277
285
|
|
|
278
286
|
/**
|
|
279
287
|
* Checks if a point lies on the Bandersnatch curve.
|
|
280
|
-
*
|
|
288
|
+
*
|
|
281
289
|
* Validates that the point satisfies the Twisted Edwards curve equation:
|
|
282
290
|
* `a*x^2 + y^2 = 1 + d*x^2*y^2` where `a = -5` and `d` is the curve parameter.
|
|
283
|
-
*
|
|
291
|
+
*
|
|
284
292
|
* @param point - The curve point to validate
|
|
285
293
|
* @returns `true` if the point is on the curve, `false` otherwise
|
|
286
294
|
*/
|
|
@@ -290,10 +298,10 @@ export class BandersnatchCurve {
|
|
|
290
298
|
|
|
291
299
|
/**
|
|
292
300
|
* Gets the generator point (base point) of the Bandersnatch curve.
|
|
293
|
-
*
|
|
301
|
+
*
|
|
294
302
|
* The generator is a point on the curve that generates the prime subgroup G.
|
|
295
303
|
* All points in the prime subgroup can be expressed as scalar multiples of the generator.
|
|
296
|
-
*
|
|
304
|
+
*
|
|
297
305
|
* @returns The generator point G
|
|
298
306
|
*/
|
|
299
307
|
static get GENERATOR() {
|
|
@@ -302,10 +310,10 @@ export class BandersnatchCurve {
|
|
|
302
310
|
|
|
303
311
|
/**
|
|
304
312
|
* Gets the identity point (point at infinity) of the Bandersnatch curve.
|
|
305
|
-
*
|
|
313
|
+
*
|
|
306
314
|
* The identity point is the neutral element for point addition:
|
|
307
315
|
* `add(point, INFINITY) === point` for any point on the curve.
|
|
308
|
-
*
|
|
316
|
+
*
|
|
309
317
|
* @returns The identity point (point at infinity)
|
|
310
318
|
*/
|
|
311
319
|
static get INFINITY() {
|
|
@@ -314,11 +322,11 @@ export class BandersnatchCurve {
|
|
|
314
322
|
|
|
315
323
|
/**
|
|
316
324
|
* Converts a curve point to its byte representation.
|
|
317
|
-
*
|
|
325
|
+
*
|
|
318
326
|
* Serializes the point to bytes, typically used for challenge generation
|
|
319
327
|
* in cryptographic protocols. The output format matches the point compression
|
|
320
328
|
* format used by the curve implementation.
|
|
321
|
-
*
|
|
329
|
+
*
|
|
322
330
|
* @param point - The curve point to hash
|
|
323
331
|
* @returns Byte representation of the point
|
|
324
332
|
* @throws {Error} If the point is invalid
|
|
@@ -329,10 +337,10 @@ export class BandersnatchCurve {
|
|
|
329
337
|
|
|
330
338
|
/**
|
|
331
339
|
* Gets the order (cardinality) of the prime subgroup of the Bandersnatch curve.
|
|
332
|
-
*
|
|
340
|
+
*
|
|
333
341
|
* The curve order is the number of points in the prime subgroup G.
|
|
334
342
|
* For any point P in G, `scalarMultiply(P, CURVE_ORDER) === INFINITY`.
|
|
335
|
-
*
|
|
343
|
+
*
|
|
336
344
|
* @returns The curve order as a bigint
|
|
337
345
|
*/
|
|
338
346
|
static get CURVE_ORDER() {
|
package/src/index.ts
CHANGED
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
* with all necessary operations for cryptographic applications.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
// Export types
|
|
9
|
-
export type { CurvePoint } from './types'
|
|
10
8
|
// Export curve parameters
|
|
11
9
|
export { BANDERSNATCH_PARAMS } from './config'
|
|
12
10
|
// Elligator2 hash-to-curve is now available in bandersnatch-vrf package
|
|
13
11
|
// Export curve implementations
|
|
14
12
|
// Temporary alias for legacy compatibility
|
|
15
13
|
export {
|
|
16
|
-
BandersnatchCurve,
|
|
17
14
|
Bandersnatch,
|
|
15
|
+
BandersnatchCurve,
|
|
18
16
|
} from './curve'
|
|
19
17
|
// VRF functionality moved to bandersnatch-vrf package
|
|
20
|
-
export * from './math'
|
|
18
|
+
export * from './math'
|
|
19
|
+
// Export types
|
|
20
|
+
export type { CurvePoint } from './types'
|
package/src/math.ts
CHANGED
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Computes the non-negative modular reduction.
|
|
13
|
-
*
|
|
13
|
+
*
|
|
14
14
|
* Returns `a mod m` where the result is always non-negative (0 <= result < m).
|
|
15
15
|
* This handles negative inputs correctly by adding the modulus to negative results.
|
|
16
|
-
*
|
|
16
|
+
*
|
|
17
17
|
* @param a - The value to reduce
|
|
18
18
|
* @param m - The modulus
|
|
19
19
|
* @returns Non-negative result of `a mod m`
|
|
@@ -25,10 +25,10 @@ export function mod(a: bigint, m: bigint): bigint {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Computes the modular inverse using the extended Euclidean algorithm.
|
|
28
|
-
*
|
|
28
|
+
*
|
|
29
29
|
* Finds the value `x` such that `(a * x) mod m = 1`. The modular inverse exists
|
|
30
30
|
* if and only if `gcd(a, m) = 1`.
|
|
31
|
-
*
|
|
31
|
+
*
|
|
32
32
|
* @param a - The value to find the inverse of
|
|
33
33
|
* @param m - The modulus
|
|
34
34
|
* @returns The modular inverse of `a` modulo `m`
|
|
@@ -53,10 +53,10 @@ export function modInverse(a: bigint, m: bigint): bigint {
|
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* Computes the modular square root using the noble package FpSqrt.
|
|
56
|
-
*
|
|
56
|
+
*
|
|
57
57
|
* Finds a value `x` such that `x^2 mod p = value`. The square root exists
|
|
58
58
|
* if and only if `value` is a quadratic residue modulo `p`.
|
|
59
|
-
*
|
|
59
|
+
*
|
|
60
60
|
* @param value - The value to find the square root of
|
|
61
61
|
* @param p - The prime modulus
|
|
62
62
|
* @param field - The field implementation from @noble/curves
|
|
@@ -81,11 +81,10 @@ export function modSqrt(
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
export function numberToBytesLittleEndian(value: bigint): Uint8Array {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
return bytes
|
|
84
|
+
const bytes = new Uint8Array(32)
|
|
85
|
+
const hex = value.toString(16).padStart(64, '0')
|
|
86
|
+
for (let i = 0; i < 32; i++) {
|
|
87
|
+
bytes[i] = Number.parseInt(hex.slice(62 - i * 2, 64 - i * 2), 16)
|
|
90
88
|
}
|
|
91
|
-
|
|
89
|
+
return bytes
|
|
90
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Represents a point on an elliptic curve.
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
* This interface defines the structure for curve points used in Bandersnatch
|
|
9
9
|
* curve operations. Points can be either finite points with (x, y) coordinates
|
|
10
10
|
* or the point at infinity.
|
|
11
|
-
*
|
|
11
|
+
*
|
|
12
12
|
* @interface CurvePoint
|
|
13
13
|
*/
|
|
14
14
|
export interface CurvePoint {
|
|
@@ -19,4 +19,3 @@ export interface CurvePoint {
|
|
|
19
19
|
/** Whether this point is the point at infinity (identity element) */
|
|
20
20
|
isInfinity: boolean
|
|
21
21
|
}
|
|
22
|
-
|