Skip to content

Commit b35fd21

Browse files
committed
edwards, ed25519, ed448: minor fixes
1 parent 218e78b commit b35fd21

3 files changed

Lines changed: 20 additions & 27 deletions

File tree

src/abstract/edwards.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,12 @@ export function edwards(params: EdwardsOpts, extraOpts: EdwardsExtraOpts = {}):
341341
const u = modP(y2 - _1n); // u = y² - 1
342342
const v = modP(d * y2 - a); // v = d y² + 1.
343343
let { isValid, value: x } = uvRatio(u, v); // √(u/v)
344-
if (!isValid) throw new Error('Point.fromBytes: invalid y coordinate');
344+
if (!isValid) throw new Error('bad point: invalid y coordinate');
345345
const isXOdd = (x & _1n) === _1n; // There are 2 square roots. Use x_0 bit to select proper
346346
const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit
347347
if (!zip215 && x === _0n && isLastByteOdd)
348348
// if x=0 and x_0 = 1, fail
349-
throw new Error('Point.fromHex: x=0 and x_0=1');
349+
throw new Error('bad point: x=0 and x_0=1');
350350
if (isLastByteOdd !== isXOdd) x = modP(-x); // if x_0 != x mod 2, set x = p-x
351351
return Point.fromAffine({ x, y });
352352
}

src/ed25519.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,28 +38,27 @@ import { montgomery, type MontgomeryECDH as XCurveFn } from './abstract/montgome
3838
import { bytesToNumberLE, ensureBytes, equalBytes, type Hex } from './utils.ts';
3939

4040
// prettier-ignore
41-
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
41+
const _0n = /* @__PURE__ */ BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
4242
// prettier-ignore
4343
const _5n = BigInt(5), _8n = BigInt(8);
4444

45-
// 2n**255n-19n
45+
// P = 2n**255n-19n
4646
const ed25519_CURVE_p = BigInt(
4747
'0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed'
4848
);
4949

50-
// P = 2n**255n - 19n
5150
// N = 2n**252n + 27742317777372353535851937790883648493n
5251
// a = Fp.create(BigInt(-1))
5352
// d = -121665/121666 a.k.a. Fp.neg(121665 * Fp.inv(121666))
54-
const ed25519_CURVE: EdwardsOpts = {
53+
const ed25519_CURVE: EdwardsOpts = /* @__PURE__ */ (() => ({
5554
p: ed25519_CURVE_p,
5655
n: BigInt('0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed'),
5756
h: _8n,
5857
a: BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec'),
5958
d: BigInt('0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3'),
6059
Gx: BigInt('0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a'),
6160
Gy: BigInt('0x6666666666666666666666666666666666666666666666666666666666666658'),
62-
};
61+
}))();
6362

6463
function ed25519_pow_2_252_3(x: bigint) {
6564
// prettier-ignore
@@ -180,7 +179,7 @@ export const ed25519ph: CurveFn = /* @__PURE__ */ (() =>
180179
* x25519.getPublicKey(x25519.utils.randomSecretKey());
181180
*/
182181
export const x25519: XCurveFn = /* @__PURE__ */ (() => {
183-
const P = ed25519.CURVE.Fp.ORDER;
182+
const P = Fp.ORDER;
184183
return montgomery({
185184
P,
186185
type: 'x25519',
@@ -196,14 +195,13 @@ export const x25519: XCurveFn = /* @__PURE__ */ (() => {
196195
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
197196
// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
198197
// SageMath returns different root first and everything falls apart
199-
200-
const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)(); // 1. c1 = (q + 3) / 8 # Integer arithmetic
198+
const ELL2_C1 = /* @__PURE__ */ (() => (ed25519_CURVE_p + _3n) / _8n)(); // 1. c1 = (q + 3) / 8 # Integer arithmetic
201199
const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))(); // 2. c2 = 2^c1
202200
const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))(); // 3. c3 = sqrt(-1)
203201

204202
// prettier-ignore
205203
function map_to_curve_elligator2_curve25519(u: bigint) {
206-
const ELL2_C4 = (Fp.ORDER - _5n) / _8n; // 4. c4 = (q - 5) / 8 # Integer arithmetic
204+
const ELL2_C4 = (ed25519_CURVE_p - _5n) / _8n; // 4. c4 = (q - 5) / 8 # Integer arithmetic
207205
const ELL2_J = BigInt(486662);
208206

209207
let tv1 = Fp.sqr(u); // 1. tv1 = u^2
@@ -274,7 +272,7 @@ export const ed25519_hasher: H2CHasher<bigint> = /* @__PURE__ */ (() =>
274272
{
275273
DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
276274
encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_',
277-
p: Fp.ORDER,
275+
p: ed25519_CURVE_p,
278276
m: 1,
279277
k: 128,
280278
expand: 'xmd',
@@ -318,7 +316,7 @@ type ExtendedPoint = EdwardsPoint;
318316
*/
319317
function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint {
320318
const { d } = ed25519_CURVE;
321-
const P = Fp.ORDER;
319+
const P = ed25519_CURVE_p;
322320
const mod = (n: bigint) => Fp.create(n);
323321
const r = mod(SQRT_M1 * r0 * r0); // 1
324322
const Ns = mod((r + _1n) * ONE_MINUS_D_SQ); // 2
@@ -494,11 +492,12 @@ export const ristretto255: {
494492
export const ristretto255_hasher: H2CHasherBase<bigint> = {
495493
hashToCurve(msg: Uint8Array, options?: htfBasicOpts): _RistrettoPoint {
496494
const DST = options?.DST || 'ristretto255_XMD:SHA-512_R255MAP_RO_';
497-
return ristretto255_map(expand_message_xmd(msg, DST, 64, sha512));
495+
const xmd = expand_message_xmd(msg, DST, 64, sha512);
496+
return ristretto255_map(xmd);
498497
},
499498
hashToScalar(msg: Uint8Array, options: htfBasicOpts = { DST: _DST_scalar }) {
500499
const xmd = expand_message_xmd(msg, options.DST, 64, sha512);
501-
return ristretto255.Point.Fn.create(bytesToNumberLE(xmd));
500+
return Fn.create(bytesToNumberLE(xmd));
502501
},
503502
};
504503

src/ed448.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@
88
*/
99
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1010
import { shake256 } from '@noble/hashes/sha3.js';
11-
import {
12-
abytes,
13-
concatBytes,
14-
utf8ToBytes,
15-
createHasher as wrapConstructor,
16-
} from '@noble/hashes/utils.js';
11+
import { abytes, concatBytes, createHasher as wrapConstructor } from '@noble/hashes/utils.js';
1712
import type { AffinePoint } from './abstract/curve.ts';
1813
import { pippenger } from './abstract/curve.ts';
1914
import {
@@ -36,7 +31,7 @@ import {
3631
} from './abstract/hash-to-curve.ts';
3732
import { Field, FpInvertBatch, isNegativeLE, mod, pow2, type IField } from './abstract/modular.ts';
3833
import { montgomery, type MontgomeryECDH as XCurveFn } from './abstract/montgomery.ts';
39-
import { bytesToNumberLE, ensureBytes, equalBytes, type Hex } from './utils.ts';
34+
import { asciiToBytes, bytesToNumberLE, ensureBytes, equalBytes, type Hex } from './utils.ts';
4035

4136
// edwards448 curve
4237
// a = 1n
@@ -153,7 +148,7 @@ const Fn448 = /* @__PURE__ */ (() => Field(ed448_CURVE.n, { BITS: 448, isLE: tru
153148
function dom4(data: Uint8Array, ctx: Uint8Array, phflag: boolean) {
154149
if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length);
155150
return concatBytes(
156-
utf8ToBytes('SigEd448'),
151+
asciiToBytes('SigEd448'),
157152
new Uint8Array([phflag ? 1 : 0, ctx.length]),
158153
ctx,
159154
data
@@ -370,9 +365,9 @@ function decaf448_map(bytes: Uint8Array): _DecafPoint {
370365
}
371366

372367
/**
373-
* Each ed448/ExtendedPoint has 4 different equivalent points. This can be
368+
* Each ed448/EdwardsPoint has 4 different equivalent points. This can be
374369
* a source of bugs for protocols like ring signatures. Decaf was created to solve this.
375-
* Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint,
370+
* Decaf point operates in X:Y:Z:T extended coordinates like EdwardsPoint,
376371
* but it should work in its own namespace: do not combine those two.
377372
* See [RFC9496](https://www.rfc-editor.org/rfc/rfc9496).
378373
*/
@@ -484,9 +479,8 @@ class _DecafPoint extends PrimeEdwardsPoint<_DecafPoint> {
484479
this.assertSame(other);
485480
const { X: X1, Y: Y1 } = this.ep;
486481
const { X: X2, Y: Y2 } = other.ep;
487-
const mod = (n: bigint) => Fp.create(n);
488482
// (x1 * y2 == y1 * x2)
489-
return mod(X1 * Y2) === mod(Y1 * X2);
483+
return Fp.create(X1 * Y2) === Fp.create(Y1 * X2);
490484
}
491485

492486
is0(): boolean {

0 commit comments

Comments
 (0)