Skip to content

Commit 77413a6

Browse files
committed
rename back coords
1 parent e1c14e6 commit 77413a6

File tree

1 file changed

+44
-40
lines changed

1 file changed

+44
-40
lines changed

index.ts

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,20 @@ const frz = (o: Object) => Object.freeze(o);
4747
export interface AffinePoint { x: bigint, y: bigint }
4848
/** Point in 3d xyz projective coordinates. 3d takes less inversions than 2d. */
4949
class Point {
50-
readonly X: bigint;
51-
readonly Y: bigint;
52-
readonly Z: bigint;
50+
readonly px: bigint;
51+
readonly py: bigint;
52+
readonly pz: bigint;
5353
constructor(X: bigint, Y: bigint, Z: bigint) {
54-
this.X = afield0(X);
55-
this.Y = afield(Y); // y can't be 0 in 3d
56-
this.Z = afield0(Z);
54+
this.px = afield0(X);
55+
this.py = afield(Y); // y can't be 0 in 3d
56+
this.pz = afield0(Z);
5757
frz(this);
5858
}
5959
static from(bytes: Bytes): Point {
6060
au8(bytes);
6161
let p: Point | undefined = undefined;
6262
const head = bytes[0], tail = bytes.subarray(1); // first byte is prefix, rest is data
63-
const x = sliceNum(tail, 0, L), len = bytes.length; // next 32 bytes are x coordinate
63+
const x = slcNum(tail, 0, L), len = bytes.length; // next 32 bytes are x coordinate
6464
if (len === (L + 1) && [0x02, 0x03].includes(head)) { // compressed points: 33b, start
6565
// afield(x); // with byte 0x02 or 0x03. check 1<=x<P.
6666
let y = lift(x); // x³ + ax + b is right side of equation
@@ -69,19 +69,19 @@ class Point {
6969
if (headOdd !== isYOdd) y = M(-y); // determine proper solution
7070
p = new Point(x, y, _1); // create point
7171
} // Uncompressed points: 65b, start with 0x04
72-
if (len === (L2 + 1) && head === 0x04) p = new Point(x, sliceNum(tail, L, L2), _1);
72+
if (len === (L2 + 1) && head === 0x04) p = new Point(x, slcNum(tail, L, L2), _1);
7373
return p ? p.ok() : err('Point invalid: not on curve'); // Verify the result
7474
}
7575
/** Equality check: compare points P&Q. */
7676
eql(other: Point): boolean {
77-
const { X: X1, Y: Y1, Z: Z1 } = this;
78-
const { X: X2, Y: Y2, Z: Z2 } = apoint(other); // isPoint() checks class equality
77+
const { px: X1, py: Y1, pz: Z1 } = this;
78+
const { px: X2, py: Y2, pz: Z2 } = apoint(other); // isPoint() checks class equality
7979
const X1Z2 = M(X1 * Z2), X2Z1 = M(X2 * Z1);
8080
const Y1Z2 = M(Y1 * Z2), Y2Z1 = M(Y2 * Z1);
8181
return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;
8282
}
8383
/** Flip point over y coordinate. */
84-
neg(): Point { return new Point(this.X, M(-this.Y), this.Z); }
84+
neg(): Point { return new Point(this.px, M(-this.py), this.pz); }
8585
/** Point doubling: P+P, complete formula. */
8686
dbl(): Point { return this.add(this); }
8787
/**
@@ -90,8 +90,8 @@ class Point {
9090
* Cost: 12M + 0S + 3*a + 3*b3 + 23add.
9191
*/
9292
add(other: Point): Point {
93-
const { X: X1, Y: Y1, Z: Z1 } = this;
94-
const { X: X2, Y: Y2, Z: Z2 } = apoint(other);
93+
const { px: X1, py: Y1, pz: Z1 } = this;
94+
const { px: X2, py: Y2, pz: Z2 } = apoint(other);
9595
const a = _0, b = _b;
9696
// const { a, b } = CURVE;
9797
let X3 = _0, Y3 = _0, Z3 = _0;
@@ -127,7 +127,7 @@ class Point {
127127
}
128128
/** Convert point to 2d xy affine point. (x, y, z) ∋ (x=x/z, y=y/z) */
129129
aff(): AffinePoint {
130-
const { X: x, Y: y, Z: z } = this;
130+
const { px: x, py: y, pz: z } = this;
131131
if (this.eql(I)) return { x: _0, y: _0 }; // fast-path for zero point
132132
if (z === _1) return { x, y }; // if z is 1, pass affine coordinates as-is
133133
const iz = inv(z, P); // z^-1: invert z
@@ -144,9 +144,13 @@ class Point {
144144
toBytes(isCompressed = true): Bytes { // Encode point to Uint8Array.
145145
const { x, y } = this.ok().aff(); // convert to 2d xy affine point
146146
const head = isCompressed ? (isEvenB(y) ? '02' : '03') : '04'; // 0x02, 0x03, 0x04 prefix
147-
const hex = head + numberToHex(x) + (isCompressed ? '' : numberToHex(y));// prefix||x and ||y
147+
const hex = head + n2h(x) + (isCompressed ? '' : n2h(y));// prefix||x and ||y
148148
return h2b(hex);
149149
}
150+
151+
// multiply(n: bigint): Point { return this.mul(n); } // Aliases to compress code
152+
// toAffine(): AffinePoint { return this.aff(); }
153+
// assertValidity(): Point { return this.ok(); }
150154
}
151155
// const { G, I } = Point; // Generator, identity points
152156
const G = new Point(Gx, Gy, _1); /** Generator / base point */
@@ -178,11 +182,11 @@ const h2b = (hex: string): Bytes => { // hex to bytes
178182
}
179183
return array;
180184
};
181-
const bytesToNum = (b: Bytes): bigint => BigInt('0x' + (b2h(b) || '0')); // bytes to number
182-
const sliceNum = (b: Bytes, from: number, to: number) => bytesToNum(b.subarray(from, to)); // slice bytes num
185+
const b2n = (b: Bytes): bigint => BigInt('0x' + (b2h(b) || '0')); // bytes to number
186+
const slcNum = (b: Bytes, from: number, to: number) => b2n(b.subarray(from, to)); // slice bytes num
183187
const numTo32b = (n: bigint): Bytes => h2b(padh(arange(n, _0, B256), L2)); // number to 32b. Must be 0 <= num < B256
184-
const numberToHex = (num: bigint): string => b2h(numTo32b(num)); // number to 32b hex
185-
const concatBytes = (...arrs: Bytes[]): Bytes => { // concatenate Uint8Array-s
188+
const n2h = (num: bigint): string => b2h(numTo32b(num)); // number to 32b hex
189+
const concatB = (...arrs: Bytes[]): Bytes => { // concatenate Uint8Array-s
186190
const r = u8n(arrs.reduce((sum, a) => sum + au8(a).length, 0)); // create u8a of summed length
187191
let pad = 0; // walk through each array,
188192
arrs.forEach(a => {r.set(a, pad); pad += a.length}); // ensure they have proper type
@@ -199,7 +203,7 @@ const inv = (num: bigint, md: bigint): bigint => { // modular inversion
199203
return b === _1 ? M(x, md) : err('no inverse'); // b is gcd at this point
200204
};
201205
const scalar = (pr: Bytes): bigint => { // normalize private key to bigint
202-
let num = bytesToNum(au8(pr, L)); // convert to bigint when bytes
206+
let num = b2n(au8(pr, L)); // convert to bigint when bytes
203207
return arange(num, _1, N, 'private key invalid 3'); // check if bigint is in range
204208
};
205209
const highS = (n: bigint): boolean => n > (N >> _1); // if a number is bigger than CURVE.n/2
@@ -222,7 +226,7 @@ class Signature {
222226
const bits2int = (bytes: Bytes): bigint => { // RFC6979: ensure ECDSA msg is X bytes.
223227
const delta = bytes.length * 8 - 256; // RFC suggests optional truncating via bits2octets
224228
if (delta > 1024) err('msg invalid'); // our CUSTOM check, "just-in-case"
225-
const num = bytesToNum(bytes); // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which
229+
const num = b2n(bytes); // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which
226230
return delta > 0 ? num >> BigInt(delta) : num; // matches bits2int. bits2int can produce res>N.
227231
};
228232
const bits2int_modN = (bytes: Bytes): bigint => { // int2octets can't be used; pads small msgs
@@ -275,7 +279,7 @@ const prepSig = (msgh: Bytes, priv: Bytes, opts: OptS = optS): BC => {// prepare
275279
}
276280
return new Signature(r, normS, rec) as SignatureWithRecovery; // use normS, not s
277281
};
278-
return { seed: concatBytes(...seed), k2sig }
282+
return { seed: concatB(...seed), k2sig }
279283
}
280284
type Pred<T> = (v: Uint8Array) => T | undefined;
281285
const hmacDrbg = <T>(asynchronous: boolean) => { // HMAC-DRBG async
@@ -374,7 +378,7 @@ const verify = (sig: Bytes, msgh: Bytes, pub: Bytes, opts: OptV = optV): boolean
374378
let { lowS } = opts; // ECDSA signature verification
375379
if (lowS == null) lowS = true; // Default lowS=true
376380
let h: bigint, P: Point; // secg.org/sec1-v2.pdf 4.1.4
377-
let { r, s } = new Signature(sliceNum(sig, 0, L), sliceNum(sig, L, L2)) // throw error when DER is suspected now.
381+
let { r, s } = new Signature(slcNum(sig, 0, L), slcNum(sig, L, L2)) // throw error when DER is suspected now.
378382
try {
379383
h = bits2int_modN(msgh); // Truncate hash
380384
P = Point.from(pub); // Validate public key
@@ -402,7 +406,7 @@ const recoverPublicKey = (point: SignatureWithRecovery, msgh: Bytes): Point => {
402406
const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n
403407
afield(radj); // ensure q.x is still a field element
404408
const head = isEvenN(rec) ? '02' : '03'; // head is 0x02 or 0x03
405-
const R = Point.from(h2b(head + numberToHex(radj))); // concat head + hex repr of r
409+
const R = Point.from(h2b(head + n2h(radj))); // concat head + hex repr of r
406410
const ir = inv(radj, N); // r^-1
407411
const u1 = modN(-h * ir); // -hr^-1
408412
const u2 = modN(s * ir); // sr^-1
@@ -433,26 +437,26 @@ const etc = {
433437
const s = subtle();
434438
const name = 'HMAC';
435439
const k = await s.importKey('raw', key, {name,hash:{name:'SHA-256'}}, false, ['sign']);
436-
return u8n(await s.sign(name, k, concatBytes(...msgs)));
440+
return u8n(await s.sign(name, k, concatB(...msgs)));
437441
},
438442
hmacSha256Sync: undefined as HmacFnSync, // For TypeScript. Actual logic is below
439443
sha256Async: async (...msgs: Bytes[]): Promise<Bytes> => {
440-
return u8n(await subtle().digest("SHA-256", concatBytes(...msgs)));
444+
return u8n(await subtle().digest("SHA-256", concatB(...msgs)));
441445
},
442446
sha256Sync: undefined as Sha256FnSync,
443447
};
444448
const etc2 = {
445449
hexToBytes: h2b as (hex: string) => Bytes,
446450
bytesToHex: b2h as (bytes: Bytes) => string,
447-
concatBytes: concatBytes as (...arrs: Bytes[]) => Bytes,
448-
bytesToNumberBE: bytesToNum as (a: Bytes) => bigint,
451+
concatBytes: concatB as (...arrs: Bytes[]) => Bytes,
452+
bytesToNumberBE: b2n as (a: Bytes) => bigint,
449453
numberToBytesBE: numTo32b as (n: bigint) => Bytes,
450454
mod: M as (a: bigint, md?: bigint) => bigint,
451455
invert: inv as (num: bigint, md?: bigint) => bigint, // math utilities
452456
randomBytes: randomBytes as (len?: number) => Bytes,
453457
}
454458
const randomPrivateKey = (): Bytes => {
455-
const num = M(bytesToNum(randomBytes(L + L / 2)), N - _1); // takes n+8 bytes
459+
const num = M(b2n(randomBytes(L + L / 2)), N - _1); // takes n+8 bytes
456460
return numTo32b(num + _1); // returns (hash mod n-1)+1
457461
}; // FIPS 186 B.4.1.
458462
/** Curve-specific utilities for private keys. */
@@ -513,12 +517,12 @@ const T_CHALLENGE = 'challenge';
513517
const taggedHash = (tag: string, ...messages: Bytes[]): Bytes => {
514518
const fn = callEtcFn('sha256Sync');
515519
const tagH = fn(getTag(tag));
516-
return fn(concatBytes(tagH, tagH, ...messages));
520+
return fn(concatB(tagH, tagH, ...messages));
517521
};
518522
const taggedHashAsync = async (tag: string, ...messages: Bytes[]): Promise<Bytes> => {.0
519523
const fn = etc.sha256Async;
520524
const tagH = await fn(getTag(tag));
521-
return await fn(concatBytes(tagH, tagH, ...messages));
525+
return await fn(concatB(tagH, tagH, ...messages));
522526
};
523527

524528
// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03
@@ -541,9 +545,9 @@ const lift = (x: bigint) => { // // Fail if x ≥ p. Let c = x³ + 7 mod p.
541545
return M(r * r) === n ? r : err('sqrt invalid'); // check if result is valid
542546
}
543547
const challenge = (...args: Bytes[]): bigint =>
544-
modN(bytesToNum(taggedHash(T_CHALLENGE, ...args)));
548+
modN(b2n(taggedHash(T_CHALLENGE, ...args)));
545549
const challengeAsync = async (...args: Bytes[]): Promise<bigint> =>
546-
modN(bytesToNum(await taggedHashAsync(T_CHALLENGE, ...args)));
550+
modN(b2n(await taggedHashAsync(T_CHALLENGE, ...args)));
547551

548552
/**
549553
* Schnorr public key is just `x` coordinate of Point as per BIP340.
@@ -559,7 +563,7 @@ const prepSigSchnorr = (message: Bytes, privateKey: Bytes, auxRand: Bytes) => {
559563
}
560564

561565
const extractK = (rand: Bytes) => {
562-
const k_ = modN(bytesToNum(rand)); // Let k' = int(rand) mod n
566+
const k_ = modN(b2n(rand)); // Let k' = int(rand) mod n
563567
if (k_ === _0) err('sign failed: k is zero'); // Fail if k' = 0.
564568
const { px, d } = extpubSchnorr(numTo32b(k_)); // Let R = k'⋅G.
565569
return { rx: px, k: d }
@@ -585,7 +589,7 @@ const signSchnorr = (
585589
): Bytes => {
586590
const { m, px, d, a } = prepSigSchnorr(message, privateKey, auxRand);
587591
const aux = taggedHash(T_AUX, a);
588-
const t = numTo32b(d ^ bytesToNum(aux)); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
592+
const t = numTo32b(d ^ b2n(aux)); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
589593
const rand = taggedHash(T_NONCE, t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
590594
const { rx, k } = extractK(rand);
591595
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
@@ -596,7 +600,7 @@ const signSchnorr = (
596600
const signAsyncSchnorr = async (message: Bytes, privateKey: Bytes, auxRand: Bytes = randomBytes(L)): Promise<Bytes> => {
597601
const { m, px, d, a } = prepSigSchnorr(message, privateKey, auxRand);
598602
const aux = await taggedHashAsync(T_AUX, a);
599-
const t = numTo32b(d ^ bytesToNum(aux)); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
603+
const t = numTo32b(d ^ b2n(aux)); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
600604
const rand = await taggedHashAsync(T_NONCE, t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
601605
const { rx, k } = extractK(rand);
602606
const e = await challengeAsync(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
@@ -619,16 +623,16 @@ const verifSchnorr = (signature: Bytes, message: Bytes, publicKey: Bytes, sync =
619623
const pub = au8(publicKey, L);
620624
// lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point.
621625
// Fail if x ≥ p. Let c = x³ + 7 mod p.
622-
const x = bytesToNum(pub);
626+
const x = b2n(pub);
623627
const y = lift(x); // Let y = c^(p+1)/4 mod p.
624628
// Return the unique point P such that x(P) = x and
625629
const P_ = new Point(x, isEvenB(y) ? y : M(-y), _1).ok(); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
626630
// P = lift_x(int(pk)); fail if that fails
627-
const r = sliceNum(sig, 0, L); // Let r = int(sig[0:32]); fail if r ≥ p.
631+
const r = slcNum(sig, 0, L); // Let r = int(sig[0:32]); fail if r ≥ p.
628632
arange(r, _1, P);
629-
const s = sliceNum(sig, L, L2); // Let s = int(sig[32:64]); fail if s ≥ n.
633+
const s = slcNum(sig, L, L2); // Let s = int(sig[32:64]); fail if s ≥ n.
630634
arange(s, _1, N);
631-
const i = concatBytes(numTo32b(r), pointToBytes(P_), msg);
635+
const i = concatB(numTo32b(r), pointToBytes(P_), msg);
632636
if (sync) return finishVerif(P_, r, s, challenge(i)); // int(challenge(bytes(r)||bytes(P)||m))%n
633637
return challengeAsync(i).then(e => finishVerif(P_, r, s, e));
634638
} catch (error) {

0 commit comments

Comments
 (0)