forked from tornado-packages/noble-curves
weierstrass: rename normalizePrivateKey to allowedPrivateKeyLengths
This commit is contained in:
parent
fcd422d246
commit
f39fb80c52
@ -24,11 +24,9 @@ export type BasicCurve<T> = AbstractCurve<T> & {
|
|||||||
b: T;
|
b: T;
|
||||||
|
|
||||||
// Optional params
|
// Optional params
|
||||||
normalizePrivateKey?: (key: PrivKey) => PrivKey; // called before privkey validation. used w p521
|
allowedPrivateKeyLengths?: readonly number[]; // for P521
|
||||||
// Whether to execute modular division on a private key, useful for bls curves with cofactor > 1
|
|
||||||
wrapPrivateKey?: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n
|
wrapPrivateKey?: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n
|
||||||
// Endomorphism options for Koblitz curves
|
endo?: EndomorphismOpts; // Endomorphism options for Koblitz curves
|
||||||
endo?: EndomorphismOpts;
|
|
||||||
// When a cofactor != 1, there can be an effective methods to:
|
// When a cofactor != 1, there can be an effective methods to:
|
||||||
// 1. Determine whether a point is torsion-free
|
// 1. Determine whether a point is torsion-free
|
||||||
isTorsionFree?: (c: ProjConstructor<T>, point: ProjPointType<T>) => boolean;
|
isTorsionFree?: (c: ProjConstructor<T>, point: ProjPointType<T>) => boolean;
|
||||||
@ -101,6 +99,14 @@ function validatePointOpts<T>(curve: CurvePointsType<T>) {
|
|||||||
if (!Fp.isValid(curve[i]))
|
if (!Fp.isValid(curve[i]))
|
||||||
throw new Error(`Invalid curve param ${i}=${opts[i]} (${typeof opts[i]})`);
|
throw new Error(`Invalid curve param ${i}=${opts[i]} (${typeof opts[i]})`);
|
||||||
}
|
}
|
||||||
|
for (const i of ['allowedPrivateKeyLengths'] as const) {
|
||||||
|
if (curve[i] === undefined) continue; // Optional
|
||||||
|
if (!Array.isArray(curve[i])) throw new Error(`Invalid ${i} array`);
|
||||||
|
}
|
||||||
|
for (const i of ['wrapPrivateKey'] as const) {
|
||||||
|
if (curve[i] === undefined) continue; // Optional
|
||||||
|
if (typeof curve[i] !== 'boolean') throw new Error(`Invalid ${i} boolean`);
|
||||||
|
}
|
||||||
for (const i of ['isTorsionFree', 'clearCofactor'] as const) {
|
for (const i of ['isTorsionFree', 'clearCofactor'] as const) {
|
||||||
if (curve[i] === undefined) continue; // Optional
|
if (curve[i] === undefined) continue; // Optional
|
||||||
if (typeof curve[i] !== 'function') throw new Error(`Invalid ${i} function`);
|
if (typeof curve[i] !== 'function') throw new Error(`Invalid ${i} function`);
|
||||||
@ -209,8 +215,13 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
// Validates if priv key is valid and converts it to bigint.
|
// Validates if priv key is valid and converts it to bigint.
|
||||||
// Supports options CURVE.normalizePrivateKey and CURVE.wrapPrivateKey.
|
// Supports options CURVE.normalizePrivateKey and CURVE.wrapPrivateKey.
|
||||||
function normalizePrivateKey(key: PrivKey): bigint {
|
function normalizePrivateKey(key: PrivKey): bigint {
|
||||||
const { normalizePrivateKey: custom, nByteLength, wrapPrivateKey, n } = CURVE;
|
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
|
||||||
if (typeof custom === 'function') key = custom(key); // CURVE.normalizePrivateKey()
|
if (lengths && typeof key !== 'bigint') {
|
||||||
|
if (key instanceof Uint8Array) key = ut.bytesToHex(key);
|
||||||
|
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
|
||||||
|
if (typeof key !== 'string' || !lengths.includes(key.length)) throw new Error('Invalid key');
|
||||||
|
key = key.padStart(nByteLength * 2, '0');
|
||||||
|
}
|
||||||
let num: bigint;
|
let num: bigint;
|
||||||
try {
|
try {
|
||||||
num = typeof key === 'bigint' ? key : ut.bytesToNumberBE(ensureBytes(key, nByteLength));
|
num = typeof key === 'bigint' ? key : ut.bytesToNumberBE(ensureBytes(key, nByteLength));
|
||||||
|
12
src/p521.ts
12
src/p521.ts
@ -1,7 +1,6 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
import { createCurve } from './_shortw_utils.js';
|
import { createCurve } from './_shortw_utils.js';
|
||||||
import { sha512 } from '@noble/hashes/sha512';
|
import { sha512 } from '@noble/hashes/sha512';
|
||||||
import { bytesToHex, PrivKey } from './abstract/utils.js';
|
|
||||||
import { Fp as Field } from './abstract/modular.js';
|
import { Fp as Field } from './abstract/modular.js';
|
||||||
import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
||||||
import * as htf from './abstract/hash-to-curve.js';
|
import * as htf from './abstract/hash-to-curve.js';
|
||||||
@ -38,16 +37,7 @@ export const P521 = createCurve({
|
|||||||
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
|
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
|
||||||
h: BigInt(1),
|
h: BigInt(1),
|
||||||
lowS: false,
|
lowS: false,
|
||||||
// P521 keys could be 130, 131, 132 bytes. We normalize to 132 bytes.
|
allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
|
||||||
// Does not replace validation; invalid keys would still be rejected.
|
|
||||||
normalizePrivateKey(key: PrivKey) {
|
|
||||||
if (typeof key === 'bigint') return key;
|
|
||||||
if (key instanceof Uint8Array) key = bytesToHex(key);
|
|
||||||
if (typeof key !== 'string' || !([130, 131, 132].includes(key.length))) {
|
|
||||||
throw new Error('Invalid key');
|
|
||||||
}
|
|
||||||
return key.padStart(66 * 2, '0'); // ensure it's always 132 bytes
|
|
||||||
},
|
|
||||||
} as const, sha512);
|
} as const, sha512);
|
||||||
export const secp521r1 = P521;
|
export const secp521r1 = P521;
|
||||||
|
|
||||||
|
@ -436,9 +436,16 @@ for (const name in CURVES) {
|
|||||||
throws(() => G[1][op](0n), '0n');
|
throws(() => G[1][op](0n), '0n');
|
||||||
G[1][op](G[2]);
|
G[1][op](G[2]);
|
||||||
throws(() => G[1][op](CURVE_ORDER), 'CURVE_ORDER');
|
throws(() => G[1][op](CURVE_ORDER), 'CURVE_ORDER');
|
||||||
|
throws(() => G[1][op](-123n), '-123n');
|
||||||
|
throws(() => G[1][op](123), '123');
|
||||||
throws(() => G[1][op](123.456), '123.456');
|
throws(() => G[1][op](123.456), '123.456');
|
||||||
throws(() => G[1][op](true), 'true');
|
throws(() => G[1][op](true), 'true');
|
||||||
|
throws(() => G[1][op](false), 'false');
|
||||||
|
throws(() => G[1][op](null), 'null');
|
||||||
|
throws(() => G[1][op](undefined), 'undefined');
|
||||||
throws(() => G[1][op]('1'), "'1'");
|
throws(() => G[1][op]('1'), "'1'");
|
||||||
|
throws(() => G[1][op]({ x: 1n, y: 1n }), '{ x: 1n, y: 1n }');
|
||||||
|
throws(() => G[1][op]({ x: 1n, y: 1n, z: 1n }), '{ x: 1n, y: 1n, z: 1n }');
|
||||||
throws(
|
throws(
|
||||||
() => G[1][op]({ x: 1n, y: 1n, z: 1n, t: 1n }),
|
() => G[1][op]({ x: 1n, y: 1n, z: 1n, t: 1n }),
|
||||||
'{ x: 1n, y: 1n, z: 1n, t: 1n }'
|
'{ x: 1n, y: 1n, z: 1n, t: 1n }'
|
||||||
@ -527,10 +534,13 @@ for (const name in CURVES) {
|
|||||||
should('.getPublicKey() type check', () => {
|
should('.getPublicKey() type check', () => {
|
||||||
throws(() => C.getPublicKey(0), '0');
|
throws(() => C.getPublicKey(0), '0');
|
||||||
throws(() => C.getPublicKey(0n), '0n');
|
throws(() => C.getPublicKey(0n), '0n');
|
||||||
throws(() => C.getPublicKey(false), 'false');
|
throws(() => C.getPublicKey(-123n), '-123n');
|
||||||
throws(() => C.getPublicKey(123), '123');
|
throws(() => C.getPublicKey(123), '123');
|
||||||
throws(() => C.getPublicKey(123.456), '123.456');
|
throws(() => C.getPublicKey(123.456), '123.456');
|
||||||
throws(() => C.getPublicKey(true), 'true');
|
throws(() => C.getPublicKey(true), 'true');
|
||||||
|
throws(() => C.getPublicKey(false), 'false');
|
||||||
|
throws(() => C.getPublicKey(null), 'null');
|
||||||
|
throws(() => C.getPublicKey(undefined), 'undefined');
|
||||||
throws(() => C.getPublicKey(''), "''");
|
throws(() => C.getPublicKey(''), "''");
|
||||||
// NOTE: passes because of disabled hex padding checks for starknet, maybe enable?
|
// NOTE: passes because of disabled hex padding checks for starknet, maybe enable?
|
||||||
// throws(() => C.getPublicKey('1'), "'1'");
|
// throws(() => C.getPublicKey('1'), "'1'");
|
||||||
@ -560,25 +570,25 @@ for (const name in CURVES) {
|
|||||||
should('.sign() edge cases', () => {
|
should('.sign() edge cases', () => {
|
||||||
throws(() => C.sign());
|
throws(() => C.sign());
|
||||||
throws(() => C.sign(''));
|
throws(() => C.sign(''));
|
||||||
|
throws(() => C.sign('', ''));
|
||||||
|
throws(() => C.sign(new Uint8Array(), new Uint8Array()));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('verify()', () => {
|
describe('verify()', () => {
|
||||||
|
const msg = '01'.repeat(32);
|
||||||
should('true for proper signatures', () => {
|
should('true for proper signatures', () => {
|
||||||
const msg = '01'.repeat(32);
|
|
||||||
const priv = C.utils.randomPrivateKey();
|
const priv = C.utils.randomPrivateKey();
|
||||||
const sig = C.sign(msg, priv);
|
const sig = C.sign(msg, priv);
|
||||||
const pub = C.getPublicKey(priv);
|
const pub = C.getPublicKey(priv);
|
||||||
deepStrictEqual(C.verify(sig, msg, pub), true);
|
deepStrictEqual(C.verify(sig, msg, pub), true);
|
||||||
});
|
});
|
||||||
should('false for wrong messages', () => {
|
should('false for wrong messages', () => {
|
||||||
const msg = '01'.repeat(32);
|
|
||||||
const priv = C.utils.randomPrivateKey();
|
const priv = C.utils.randomPrivateKey();
|
||||||
const sig = C.sign(msg, priv);
|
const sig = C.sign(msg, priv);
|
||||||
const pub = C.getPublicKey(priv);
|
const pub = C.getPublicKey(priv);
|
||||||
deepStrictEqual(C.verify(sig, '11'.repeat(32), pub), false);
|
deepStrictEqual(C.verify(sig, '11'.repeat(32), pub), false);
|
||||||
});
|
});
|
||||||
should('false for wrong keys', () => {
|
should('false for wrong keys', () => {
|
||||||
const msg = '01'.repeat(32);
|
|
||||||
const priv = C.utils.randomPrivateKey();
|
const priv = C.utils.randomPrivateKey();
|
||||||
const sig = C.sign(msg, priv);
|
const sig = C.sign(msg, priv);
|
||||||
deepStrictEqual(C.verify(sig, msg, C.getPublicKey(C.utils.randomPrivateKey())), false);
|
deepStrictEqual(C.verify(sig, msg, C.getPublicKey(C.utils.randomPrivateKey())), false);
|
||||||
|
Loading…
Reference in New Issue
Block a user