forked from tornado-packages/noble-curves
weierstrass, montgomery, secp: add comments
This commit is contained in:
parent
26ebb5dcce
commit
e1cb8549e8
@ -4,8 +4,8 @@
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| >=0.5.0 | :white_check_mark: |
|
||||
| <0.5.0 | :x: |
|
||||
| >=1.0.0 | :white_check_mark: |
|
||||
| <1.0.0 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
@ -73,6 +73,7 @@ export function montgomery(curveDef: CurveType): CurveFn {
|
||||
return [x_2, x_3];
|
||||
}
|
||||
|
||||
// Accepts 0 as well
|
||||
function assertFieldElement(n: bigint): bigint {
|
||||
if (typeof n === 'bigint' && _0n <= n && n < P) return n;
|
||||
throw new Error('Expected valid scalar 0 < scalar < CURVE.P');
|
||||
|
@ -642,7 +642,6 @@ export type CurveFn = {
|
||||
utils: {
|
||||
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
||||
isValidPrivateKey(privateKey: PrivKey): boolean;
|
||||
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
||||
randomPrivateKey: () => Uint8Array;
|
||||
precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
|
||||
};
|
||||
@ -677,7 +676,6 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
||||
const x = Fp.toBytes(a.x);
|
||||
const cat = ut.concatBytes;
|
||||
if (isCompressed) {
|
||||
// TODO: hasEvenY
|
||||
return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
|
||||
} else {
|
||||
return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
|
||||
@ -809,17 +807,15 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
||||
},
|
||||
normPrivateKeyToScalar: normalizePrivateKey,
|
||||
|
||||
/**
|
||||
* Converts some bytes to a valid private key. Needs at least (nBitLength+64) bytes.
|
||||
*/
|
||||
hashToPrivateKey: (hash: Hex): Uint8Array =>
|
||||
ut.numberToBytesBE(mod.hashToPrivateScalar(hash, CURVE_ORDER), CURVE.nByteLength),
|
||||
|
||||
/**
|
||||
* Produces cryptographically secure private key from random of size (nBitLength+64)
|
||||
* as per FIPS 186 B.4.1 with modulo bias being neglible.
|
||||
*/
|
||||
randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(CURVE.randomBytes(Fp.BYTES + 8)),
|
||||
randomPrivateKey: (): Uint8Array => {
|
||||
const rand = CURVE.randomBytes(Fp.BYTES + 8);
|
||||
const num = mod.hashToPrivateScalar(rand, CURVE_ORDER);
|
||||
return ut.numberToBytesBE(num, CURVE.nByteLength);
|
||||
},
|
||||
|
||||
/**
|
||||
* 1. Returns cached point which you can use to pass to `getSharedSecret` or `#multiply` by it.
|
||||
@ -862,7 +858,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
||||
/**
|
||||
* ECDH (Elliptic Curve Diffie Hellman).
|
||||
* Computes shared public key from private key and public key.
|
||||
* Checks: 1) private key validity 2) shared key is on-curve
|
||||
* Checks: 1) private key validity 2) shared key is on-curve.
|
||||
* Does NOT hash the result.
|
||||
* @param privateA private key
|
||||
* @param publicB different public key
|
||||
* @param isCompressed whether to return compact (default), or full key
|
||||
@ -895,10 +892,12 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
||||
};
|
||||
// NOTE: pads output with zero as per spec
|
||||
const ORDER_MASK = ut.bitMask(CURVE.nBitLength);
|
||||
/**
|
||||
* Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
|
||||
*/
|
||||
function int2octets(num: bigint): Uint8Array {
|
||||
if (typeof num !== 'bigint') throw new Error('bigint expected');
|
||||
if (!(_0n <= num && num < ORDER_MASK))
|
||||
// n in [0..ORDER_MASK-1]
|
||||
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
|
||||
// works with order, can have different size than numToField!
|
||||
return ut.numberToBytesBE(num, CURVE.nByteLength);
|
||||
|
@ -107,6 +107,7 @@ function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {
|
||||
return sha256(concatBytes(tagP, ...messages));
|
||||
}
|
||||
|
||||
// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03
|
||||
const pointToBytes = (point: PointType<bigint>) => point.toRawBytes(true).slice(1);
|
||||
const numTo32b = (n: bigint) => numberToBytesBE(n, 32);
|
||||
const modP = (x: bigint) => mod(x, secp256k1P);
|
||||
@ -114,12 +115,17 @@ const modN = (x: bigint) => mod(x, secp256k1N);
|
||||
const Point = secp256k1.ProjectivePoint;
|
||||
const GmulAdd = (Q: PointType<bigint>, a: bigint, b: bigint) =>
|
||||
Point.BASE.multiplyAndAddUnsafe(Q, a, b);
|
||||
// Calculate point, scalar and bytes
|
||||
function schnorrGetExtPubKey(priv: PrivKey) {
|
||||
const d = secp256k1.utils.normPrivateKeyToScalar(priv);
|
||||
const d = secp256k1.utils.normPrivateKeyToScalar(priv); // same method executed in fromPrivateKey
|
||||
const point = Point.fromPrivateKey(d); // P = d'⋅G; 0 < d' < n check is done inside
|
||||
const scalar = point.hasEvenY() ? d : modN(-d); // d = d' if has_even_y(P), otherwise d = n-d'
|
||||
return { point, scalar, bytes: pointToBytes(point) };
|
||||
}
|
||||
/**
|
||||
* lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point.
|
||||
* @returns valid point checked for being on-curve
|
||||
*/
|
||||
function lift_x(x: bigint): PointType<bigint> {
|
||||
if (!fe(x)) throw new Error('bad x: need 0 < x < p'); // Fail if x ≥ p.
|
||||
const xx = modP(x * x);
|
||||
@ -130,6 +136,9 @@ function lift_x(x: bigint): PointType<bigint> {
|
||||
p.assertValidity();
|
||||
return p;
|
||||
}
|
||||
/**
|
||||
* Create tagged hash, convert it to bigint, reduce modulo-n.
|
||||
*/
|
||||
function challenge(...args: Uint8Array[]): bigint {
|
||||
return modN(bytesToNumberBE(taggedHash('BIP0340/challenge', ...args)));
|
||||
}
|
||||
@ -169,6 +178,7 @@ function schnorrSign(
|
||||
|
||||
/**
|
||||
* Verifies Schnorr signature.
|
||||
* Will swallow errors & return false except for initial type validation of arguments.
|
||||
*/
|
||||
function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean {
|
||||
const sig = ensureBytes('signature', signature, 64);
|
||||
|
Loading…
Reference in New Issue
Block a user