@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.
@@ -32,8 +32,6 @@ jobs:
32
32
  - name: Install dependencies
33
33
  run: |
34
34
  bun install
35
- # Ensure TypeDoc can find all dependencies
36
- bun install --frozen-lockfile || bun install
37
35
 
38
36
  - name: Generate documentation
39
37
  run: bun run docs
package/LICENSE CHANGED
@@ -201,3 +201,6 @@
201
201
  See the License for the specific language governing permissions and
202
202
  limitations under the License.
203
203
 
204
+
205
+
206
+
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@pbnjam/bandersnatch",
3
- "version": "0.7.2-rc0",
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": "^2.0.1",
23
- "@noble/hashes": "^2.0.1"
22
+ "@noble/curves": "2.0.1",
23
+ "@noble/hashes": "2.0.1"
24
24
  },
25
25
  "devDependencies": {
26
- "@types/bun": "^1.3.1",
26
+ "@types/bun": "1.3.5",
27
27
  "@types/node": "^22.0.0",
28
- "bun-types": "^1.3.1",
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. Validates the point is in the prime subgroup G
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 the point is not in the prime subgroup G
111
+ * @throws {Error} If validatePointOnCurve is true and point is not on the curve
109
112
  */
110
- static bytesToPoint(bytes: Uint8Array): EdwardsPoint {
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
- // Validate point is in prime subgroup as required by bandersnatch-vrf-spec section 2.1:
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
- const curveOrderMinusOne = BANDERSNATCH_PARAMS.CURVE_ORDER - 1n
178
- const pointTimesOrderMinusOne = this.scalarMultiply(
179
- point,
180
- curveOrderMinusOne,
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
- 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)
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
-