hash-to-curve: more type checks. Rename method to createHasher
This commit is contained in:
parent
98ea15dca4
commit
80966cbd03
@ -3,7 +3,8 @@
|
|||||||
"version": "0.6.4",
|
"version": "0.6.4",
|
||||||
"description": "Minimal, auditable JS implementation of elliptic curve cryptography",
|
"description": "Minimal, auditable JS implementation of elliptic curve cryptography",
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib",
|
||||||
|
"src"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"bench": "cd benchmark; node secp256k1.js; node curves.js; node stark.js; node bls.js",
|
"bench": "cd benchmark; node secp256k1.js; node curves.js; node stark.js; node bls.js",
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
import { AffinePoint } from './curve.js';
|
import { AffinePoint } from './curve.js';
|
||||||
import { Field, hashToPrivateScalar } from './modular.js';
|
import { Field, hashToPrivateScalar } from './modular.js';
|
||||||
import { Hex, PrivKey, CHash, bitLen, bitGet, hexToBytes, bytesToHex } from './utils.js';
|
import { Hex, PrivKey, CHash, bitLen, bitGet, ensureBytes } from './utils.js';
|
||||||
import * as htf from './hash-to-curve.js';
|
import * as htf from './hash-to-curve.js';
|
||||||
import {
|
import {
|
||||||
CurvePointsType,
|
CurvePointsType,
|
||||||
@ -67,16 +67,11 @@ export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
|
|||||||
Fp2: Field<Fp2>;
|
Fp2: Field<Fp2>;
|
||||||
Fp6: Field<Fp6>;
|
Fp6: Field<Fp6>;
|
||||||
Fp12: Field<Fp12>;
|
Fp12: Field<Fp12>;
|
||||||
G1: CurvePointsRes<Fp>;
|
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
|
||||||
G2: CurvePointsRes<Fp2>;
|
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
|
||||||
Signature: SignatureCoder<Fp2>;
|
Signature: SignatureCoder<Fp2>;
|
||||||
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
|
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
|
||||||
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
|
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
|
||||||
// prettier-ignore
|
|
||||||
hashToCurve: {
|
|
||||||
G1: ReturnType<(typeof htf.hashToCurve<Fp>)>,
|
|
||||||
G2: ReturnType<(typeof htf.hashToCurve<Fp2>)>,
|
|
||||||
},
|
|
||||||
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
|
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
|
||||||
getPublicKey: (privateKey: PrivKey) => Uint8Array;
|
getPublicKey: (privateKey: PrivKey) => Uint8Array;
|
||||||
sign: {
|
sign: {
|
||||||
@ -102,16 +97,14 @@ export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
|
|||||||
publicKeys: (Hex | ProjPointType<Fp>)[]
|
publicKeys: (Hex | ProjPointType<Fp>)[]
|
||||||
) => boolean;
|
) => boolean;
|
||||||
utils: {
|
utils: {
|
||||||
stringToBytes: typeof htf.stringToBytes;
|
randomPrivateKey: () => Uint8Array;
|
||||||
hashToField: typeof htf.hash_to_field;
|
|
||||||
expandMessageXMD: typeof htf.expand_message_xmd;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function bls<Fp2, Fp6, Fp12>(
|
export function bls<Fp2, Fp6, Fp12>(
|
||||||
CURVE: CurveType<Fp, Fp2, Fp6, Fp12>
|
CURVE: CurveType<Fp, Fp2, Fp6, Fp12>
|
||||||
): CurveFn<Fp, Fp2, Fp6, Fp12> {
|
): CurveFn<Fp, Fp2, Fp6, Fp12> {
|
||||||
// Fields looks pretty specific for curve, so for now we need to pass them with options
|
// Fields looks pretty specific for curve, so for now we need to pass them with opts
|
||||||
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
|
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
|
||||||
const BLS_X_LEN = bitLen(CURVE.x);
|
const BLS_X_LEN = bitLen(CURVE.x);
|
||||||
const groupLen = 32; // TODO: calculate; hardcoded for now
|
const groupLen = 32; // TODO: calculate; hardcoded for now
|
||||||
@ -180,31 +173,20 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const utils = {
|
const utils = {
|
||||||
hexToBytes: hexToBytes,
|
randomPrivateKey: (): Uint8Array => {
|
||||||
bytesToHex: bytesToHex,
|
return Fr.toBytes(hashToPrivateScalar(CURVE.randomBytes(groupLen + 8), CURVE.r));
|
||||||
stringToBytes: htf.stringToBytes,
|
},
|
||||||
// TODO: do we need to export it here?
|
|
||||||
hashToField: (
|
|
||||||
msg: Uint8Array,
|
|
||||||
count: number,
|
|
||||||
options: Partial<typeof CURVE.htfDefaults> = {}
|
|
||||||
) => htf.hash_to_field(msg, count, { ...CURVE.htfDefaults, ...options }),
|
|
||||||
expandMessageXMD: (msg: Uint8Array, DST: Uint8Array, lenInBytes: number, H = CURVE.hash) =>
|
|
||||||
htf.expand_message_xmd(msg, DST, lenInBytes, H),
|
|
||||||
hashToPrivateKey: (hash: Hex): Uint8Array => Fr.toBytes(hashToPrivateScalar(hash, CURVE.r)),
|
|
||||||
randomBytes: (bytesLength: number = groupLen): Uint8Array => CURVE.randomBytes(bytesLength),
|
|
||||||
randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Point on G1 curve: (x, y)
|
// Point on G1 curve: (x, y)
|
||||||
const G1 = weierstrassPoints({
|
const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 });
|
||||||
n: Fr.ORDER,
|
const G1 = Object.assign(
|
||||||
...CURVE.G1,
|
G1_,
|
||||||
});
|
htf.createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
|
||||||
const G1HashToCurve = htf.hashToCurve(G1.ProjectivePoint, CURVE.G1.mapToCurve, {
|
|
||||||
...CURVE.htfDefaults,
|
...CURVE.htfDefaults,
|
||||||
...CURVE.G1.htfDefaults,
|
...CURVE.G1.htfDefaults,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// Sparse multiplication against precomputed coefficients
|
// Sparse multiplication against precomputed coefficients
|
||||||
// TODO: replace with weakmap?
|
// TODO: replace with weakmap?
|
||||||
@ -223,15 +205,14 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
|
// Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
|
||||||
const G2 = weierstrassPoints({
|
const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 });
|
||||||
n: Fr.ORDER,
|
const G2 = Object.assign(
|
||||||
...CURVE.G2,
|
G2_,
|
||||||
});
|
htf.createHasher(G2_.ProjectivePoint as htf.H2CPointConstructor<Fp2>, CURVE.G2.mapToCurve, {
|
||||||
const C = G2.ProjectivePoint as htf.H2CPointConstructor<Fp2>; // TODO: fix
|
|
||||||
const G2HashToCurve = htf.hashToCurve(C, CURVE.G2.mapToCurve, {
|
|
||||||
...CURVE.htfDefaults,
|
...CURVE.htfDefaults,
|
||||||
...CURVE.G2.htfDefaults,
|
...CURVE.G2.htfDefaults,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const { Signature } = CURVE.G2;
|
const { Signature } = CURVE.G2;
|
||||||
|
|
||||||
@ -260,7 +241,7 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
function normP2Hash(point: G2Hex, htfOpts?: htf.htfBasicOpts): G2 {
|
function normP2Hash(point: G2Hex, htfOpts?: htf.htfBasicOpts): G2 {
|
||||||
return point instanceof G2.ProjectivePoint
|
return point instanceof G2.ProjectivePoint
|
||||||
? point
|
? point
|
||||||
: (G2HashToCurve.hashToCurve(point, htfOpts) as G2);
|
: (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies generator by private key.
|
// Multiplies generator by private key.
|
||||||
@ -383,7 +364,6 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
Signature,
|
Signature,
|
||||||
millerLoop,
|
millerLoop,
|
||||||
calcPairingPrecomputes,
|
calcPairingPrecomputes,
|
||||||
hashToCurve: { G1: G1HashToCurve, G2: G2HashToCurve },
|
|
||||||
pairing,
|
pairing,
|
||||||
getPublicKey,
|
getPublicKey,
|
||||||
sign,
|
sign,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
|
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
|
||||||
import { mod, Field } from './modular.js';
|
import { mod, Field } from './modular.js';
|
||||||
import { CHash, Hex, concatBytes, ensureBytes, validateObject } from './utils.js';
|
import { CHash, concatBytes, utf8ToBytes, validateObject } from './utils.js';
|
||||||
|
|
||||||
export type Opts = {
|
export type Opts = {
|
||||||
DST: string; // DST: a domain separation tag, defined in section 2.2.5
|
DST: string; // DST: a domain separation tag, defined in section 2.2.5
|
||||||
@ -17,18 +17,6 @@ export type Opts = {
|
|||||||
hash: CHash;
|
hash: CHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global symbols in both browsers and Node.js since v11
|
|
||||||
// See https://github.com/microsoft/TypeScript/issues/31535
|
|
||||||
declare const TextEncoder: any;
|
|
||||||
declare const TextDecoder: any;
|
|
||||||
|
|
||||||
export function stringToBytes(str: string): Uint8Array {
|
|
||||||
if (typeof str !== 'string') {
|
|
||||||
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
||||||
}
|
|
||||||
return new TextEncoder().encode(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Octet Stream to Integer (bytesToNumberBE)
|
// Octet Stream to Integer (bytesToNumberBE)
|
||||||
function os2ip(bytes: Uint8Array): bigint {
|
function os2ip(bytes: Uint8Array): bigint {
|
||||||
let result = 0n;
|
let result = 0n;
|
||||||
@ -60,6 +48,13 @@ function strxor(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isBytes(item: unknown): void {
|
||||||
|
if (!(item instanceof Uint8Array)) throw new Error('Uint8Array expected');
|
||||||
|
}
|
||||||
|
function isNum(item: unknown): void {
|
||||||
|
if (!Number.isSafeInteger(item)) throw new Error('number expected');
|
||||||
|
}
|
||||||
|
|
||||||
// Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits
|
// Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1
|
||||||
export function expand_message_xmd(
|
export function expand_message_xmd(
|
||||||
@ -68,8 +63,11 @@ export function expand_message_xmd(
|
|||||||
lenInBytes: number,
|
lenInBytes: number,
|
||||||
H: CHash
|
H: CHash
|
||||||
): Uint8Array {
|
): Uint8Array {
|
||||||
|
isBytes(msg);
|
||||||
|
isBytes(DST);
|
||||||
|
isNum(lenInBytes);
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
||||||
if (DST.length > 255) DST = H(concatBytes(stringToBytes('H2C-OVERSIZE-DST-'), DST));
|
if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST));
|
||||||
const b_in_bytes = H.outputLen;
|
const b_in_bytes = H.outputLen;
|
||||||
const r_in_bytes = H.blockLen;
|
const r_in_bytes = H.blockLen;
|
||||||
const ell = Math.ceil(lenInBytes / b_in_bytes);
|
const ell = Math.ceil(lenInBytes / b_in_bytes);
|
||||||
@ -95,11 +93,14 @@ export function expand_message_xof(
|
|||||||
k: number,
|
k: number,
|
||||||
H: CHash
|
H: CHash
|
||||||
): Uint8Array {
|
): Uint8Array {
|
||||||
|
isBytes(msg);
|
||||||
|
isBytes(DST);
|
||||||
|
isNum(lenInBytes);
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
||||||
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
||||||
if (DST.length > 255) {
|
if (DST.length > 255) {
|
||||||
const dkLen = Math.ceil((2 * k) / 8);
|
const dkLen = Math.ceil((2 * k) / 8);
|
||||||
DST = H.create({ dkLen }).update(stringToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
|
DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
|
||||||
}
|
}
|
||||||
if (lenInBytes > 65535 || DST.length > 255)
|
if (lenInBytes > 65535 || DST.length > 255)
|
||||||
throw new Error('expand_message_xof: invalid lenInBytes');
|
throw new Error('expand_message_xof: invalid lenInBytes');
|
||||||
@ -123,25 +124,27 @@ export function expand_message_xof(
|
|||||||
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
|
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
|
||||||
*/
|
*/
|
||||||
export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] {
|
export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] {
|
||||||
// if options is provided but incomplete, fill any missing fields with the
|
const { p, k, m, hash, expand, DST: _DST } = options;
|
||||||
// value in hftDefaults (ie hash to G2).
|
isBytes(msg);
|
||||||
const log2p = options.p.toString(2).length;
|
isNum(count);
|
||||||
const L = Math.ceil((log2p + options.k) / 8); // section 5.1 of ietf draft link above
|
if (typeof _DST !== 'string') throw new Error('DST must be valid');
|
||||||
const len_in_bytes = count * options.m * L;
|
const log2p = p.toString(2).length;
|
||||||
const DST = stringToBytes(options.DST);
|
const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above
|
||||||
let pseudo_random_bytes = msg;
|
const len_in_bytes = count * m * L;
|
||||||
if (options.expand === 'xmd') {
|
const DST = utf8ToBytes(_DST);
|
||||||
pseudo_random_bytes = expand_message_xmd(msg, DST, len_in_bytes, options.hash);
|
const pseudo_random_bytes =
|
||||||
} else if (options.expand === 'xof') {
|
expand === 'xmd'
|
||||||
pseudo_random_bytes = expand_message_xof(msg, DST, len_in_bytes, options.k, options.hash);
|
? expand_message_xmd(msg, DST, len_in_bytes, hash)
|
||||||
}
|
: expand === 'xof'
|
||||||
|
? expand_message_xof(msg, DST, len_in_bytes, k, hash)
|
||||||
|
: msg;
|
||||||
const u = new Array(count);
|
const u = new Array(count);
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const e = new Array(options.m);
|
const e = new Array(m);
|
||||||
for (let j = 0; j < options.m; j++) {
|
for (let j = 0; j < m; j++) {
|
||||||
const elm_offset = L * (j + i * options.m);
|
const elm_offset = L * (j + i * m);
|
||||||
const tv = pseudo_random_bytes.subarray(elm_offset, elm_offset + L);
|
const tv = pseudo_random_bytes.subarray(elm_offset, elm_offset + L);
|
||||||
e[j] = mod(os2ip(tv), options.p);
|
e[j] = mod(os2ip(tv), p);
|
||||||
}
|
}
|
||||||
u[i] = e;
|
u[i] = e;
|
||||||
}
|
}
|
||||||
@ -178,7 +181,7 @@ export type MapToCurve<T> = (scalar: bigint[]) => AffinePoint<T>;
|
|||||||
// (changing DST is ok!)
|
// (changing DST is ok!)
|
||||||
export type htfBasicOpts = { DST: string };
|
export type htfBasicOpts = { DST: string };
|
||||||
|
|
||||||
export function hashToCurve<T>(
|
export function createHasher<T>(
|
||||||
Point: H2CPointConstructor<T>,
|
Point: H2CPointConstructor<T>,
|
||||||
mapToCurve: MapToCurve<T>,
|
mapToCurve: MapToCurve<T>,
|
||||||
def: Opts
|
def: Opts
|
||||||
@ -197,21 +200,17 @@ export function hashToCurve<T>(
|
|||||||
return {
|
return {
|
||||||
// Encodes byte string to elliptic curve
|
// Encodes byte string to elliptic curve
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
|
||||||
hashToCurve(msg: Hex, options?: htfBasicOpts) {
|
hashToCurve(msg: Uint8Array, options?: htfBasicOpts) {
|
||||||
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
|
||||||
msg = ensureBytes(msg);
|
|
||||||
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts);
|
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts);
|
||||||
const P = Point.fromAffine(mapToCurve(u[0]))
|
const u0 = Point.fromAffine(mapToCurve(u[0]));
|
||||||
.add(Point.fromAffine(mapToCurve(u[1])))
|
const u1 = Point.fromAffine(mapToCurve(u[1]));
|
||||||
.clearCofactor();
|
const P = u0.add(u1).clearCofactor();
|
||||||
P.assertValidity();
|
P.assertValidity();
|
||||||
return P;
|
return P;
|
||||||
},
|
},
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
||||||
encodeToCurve(msg: Hex, options?: htfBasicOpts) {
|
encodeToCurve(msg: Uint8Array, options?: htfBasicOpts) {
|
||||||
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
|
||||||
msg = ensureBytes(msg);
|
|
||||||
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts);
|
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts);
|
||||||
const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
|
const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
|
||||||
P.assertValidity();
|
P.assertValidity();
|
||||||
|
@ -149,13 +149,13 @@ export function montgomery(curveDef: CurveType): CurveFn {
|
|||||||
// MUST mask the most significant bit in the final byte.
|
// MUST mask the most significant bit in the final byte.
|
||||||
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
|
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
|
||||||
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
|
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
|
||||||
const u = ensureBytes(uEnc, montgomeryBytes);
|
const u = ensureBytes('u coordinate', uEnc, montgomeryBytes);
|
||||||
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
|
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
|
||||||
if (fieldLen === montgomeryBytes) u[fieldLen - 1] &= 127; // 0b0111_1111
|
if (fieldLen === montgomeryBytes) u[fieldLen - 1] &= 127; // 0b0111_1111
|
||||||
return bytesToNumberLE(u);
|
return bytesToNumberLE(u);
|
||||||
}
|
}
|
||||||
function decodeScalar(n: Hex): bigint {
|
function decodeScalar(n: Hex): bigint {
|
||||||
const bytes = ensureBytes(n);
|
const bytes = ensureBytes('scalar', n);
|
||||||
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)
|
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)
|
||||||
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
|
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
|
||||||
return bytesToNumberLE(adjustScalarBytes(bytes));
|
return bytesToNumberLE(adjustScalarBytes(bytes));
|
||||||
|
@ -944,7 +944,7 @@ function G2psi2(c: ProjConstructor<Fp2>, P: ProjPointType<Fp2>) {
|
|||||||
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
|
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
|
||||||
// m = 2 (or 1 for G1 see section 8.8.1)
|
// m = 2 (or 1 for G1 see section 8.8.1)
|
||||||
// k = 128
|
// k = 128
|
||||||
const htfDefaults = {
|
const htfDefaults = Object.freeze({
|
||||||
// DST: a domain separation tag
|
// DST: a domain separation tag
|
||||||
// defined in section 2.2.5
|
// defined in section 2.2.5
|
||||||
// Use utils.getDSTLabel(), utils.setDSTLabel(value)
|
// Use utils.getDSTLabel(), utils.setDSTLabel(value)
|
||||||
@ -966,7 +966,7 @@ const htfDefaults = {
|
|||||||
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
||||||
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|
||||||
hash: sha256,
|
hash: sha256,
|
||||||
} as const;
|
} as const);
|
||||||
|
|
||||||
// Encoding utils
|
// Encoding utils
|
||||||
// Point on G1 curve: (x, y)
|
// Point on G1 curve: (x, y)
|
||||||
@ -1220,7 +1220,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
|
|||||||
Signature: {
|
Signature: {
|
||||||
// TODO: Optimize, it's very slow because of sqrt.
|
// TODO: Optimize, it's very slow because of sqrt.
|
||||||
decode(hex: Hex): ProjPointType<Fp2> {
|
decode(hex: Hex): ProjPointType<Fp2> {
|
||||||
hex = ensureBytes(hex);
|
hex = ensureBytes('signatureHex', hex);
|
||||||
const P = Fp.ORDER;
|
const P = Fp.ORDER;
|
||||||
const half = hex.length / 2;
|
const half = hex.length / 2;
|
||||||
if (half !== 48 && half !== 96)
|
if (half !== 48 && half !== 96)
|
||||||
@ -1247,7 +1247,6 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
|
|||||||
const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1;
|
const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1;
|
||||||
if (isGreater || isZero) y = Fp2.neg(y);
|
if (isGreater || isZero) y = Fp2.neg(y);
|
||||||
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
|
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
|
||||||
// console.log('Signature.decode', point);
|
|
||||||
point.assertValidity();
|
point.assertValidity();
|
||||||
return point;
|
return point;
|
||||||
},
|
},
|
||||||
|
@ -5,12 +5,12 @@ import { twistedEdwards, ExtPointType } from './abstract/edwards.js';
|
|||||||
import { montgomery } from './abstract/montgomery.js';
|
import { montgomery } from './abstract/montgomery.js';
|
||||||
import { mod, pow2, isNegativeLE, Fp as Field, FpSqrtEven } from './abstract/modular.js';
|
import { mod, pow2, isNegativeLE, Fp as Field, FpSqrtEven } from './abstract/modular.js';
|
||||||
import {
|
import {
|
||||||
ensureBytes,
|
|
||||||
equalBytes,
|
equalBytes,
|
||||||
bytesToHex,
|
bytesToHex,
|
||||||
bytesToNumberLE,
|
bytesToNumberLE,
|
||||||
numberToBytesLE,
|
numberToBytesLE,
|
||||||
Hex,
|
Hex,
|
||||||
|
ensureBytes,
|
||||||
} from './abstract/utils.js';
|
} from './abstract/utils.js';
|
||||||
import * as htf from './abstract/hash-to-curve.js';
|
import * as htf from './abstract/hash-to-curve.js';
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ function map_to_curve_elligator2_edwards25519(u: bigint) {
|
|||||||
const inv = Fp.invertBatch([xd, yd]); // batch division
|
const inv = Fp.invertBatch([xd, yd]); // batch division
|
||||||
return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
|
return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
|
||||||
}
|
}
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
ed25519.ExtendedPoint,
|
ed25519.ExtendedPoint,
|
||||||
(scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
(scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
||||||
{
|
{
|
||||||
@ -316,7 +316,7 @@ export class RistrettoPoint {
|
|||||||
* @param hex 64-bit output of a hash function
|
* @param hex 64-bit output of a hash function
|
||||||
*/
|
*/
|
||||||
static hashToCurve(hex: Hex): RistrettoPoint {
|
static hashToCurve(hex: Hex): RistrettoPoint {
|
||||||
hex = ensureBytes(hex, 64);
|
hex = ensureBytes('ristrettoHash', hex, 64);
|
||||||
const r1 = bytes255ToNumberLE(hex.slice(0, 32));
|
const r1 = bytes255ToNumberLE(hex.slice(0, 32));
|
||||||
const R1 = calcElligatorRistrettoMap(r1);
|
const R1 = calcElligatorRistrettoMap(r1);
|
||||||
const r2 = bytes255ToNumberLE(hex.slice(32, 64));
|
const r2 = bytes255ToNumberLE(hex.slice(32, 64));
|
||||||
@ -330,7 +330,7 @@ export class RistrettoPoint {
|
|||||||
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
||||||
*/
|
*/
|
||||||
static fromHex(hex: Hex): RistrettoPoint {
|
static fromHex(hex: Hex): RistrettoPoint {
|
||||||
hex = ensureBytes(hex, 32);
|
hex = ensureBytes('ristrettoHex', hex, 32);
|
||||||
const { a, d } = ed25519.CURVE;
|
const { a, d } = ed25519.CURVE;
|
||||||
const P = ed25519.CURVE.Fp.ORDER;
|
const P = ed25519.CURVE.Fp.ORDER;
|
||||||
const mod = ed25519.CURVE.Fp.create;
|
const mod = ed25519.CURVE.Fp.create;
|
||||||
|
@ -225,7 +225,7 @@ function map_to_curve_elligator2_edwards448(u: bigint) {
|
|||||||
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
|
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
ed448.ExtendedPoint,
|
ed448.ExtendedPoint,
|
||||||
(scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]),
|
(scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]),
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@ export const P256 = createCurve(
|
|||||||
);
|
);
|
||||||
export const secp256r1 = P256;
|
export const secp256r1 = P256;
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
secp256r1.ProjectivePoint,
|
secp256r1.ProjectivePoint,
|
||||||
(scalars: bigint[]) => mapSWU(scalars[0]),
|
(scalars: bigint[]) => mapSWU(scalars[0]),
|
||||||
{
|
{
|
||||||
|
@ -41,7 +41,7 @@ export const P384 = createCurve({
|
|||||||
);
|
);
|
||||||
export const secp384r1 = P384;
|
export const secp384r1 = P384;
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
secp384r1.ProjectivePoint,
|
secp384r1.ProjectivePoint,
|
||||||
(scalars: bigint[]) => mapSWU(scalars[0]),
|
(scalars: bigint[]) => mapSWU(scalars[0]),
|
||||||
{
|
{
|
||||||
|
@ -41,7 +41,7 @@ export const P521 = createCurve({
|
|||||||
} as const, sha512);
|
} as const, sha512);
|
||||||
export const secp521r1 = P521;
|
export const secp521r1 = P521;
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
secp521r1.ProjectivePoint,
|
secp521r1.ProjectivePoint,
|
||||||
(scalars: bigint[]) => mapSWU(scalars[0]),
|
(scalars: bigint[]) => mapSWU(scalars[0]),
|
||||||
{
|
{
|
||||||
|
@ -242,7 +242,7 @@ const mapSWU = mapToCurveSimpleSWU(Fp, {
|
|||||||
B: BigInt('1771'),
|
B: BigInt('1771'),
|
||||||
Z: Fp.create(BigInt('-11')),
|
Z: Fp.create(BigInt('-11')),
|
||||||
});
|
});
|
||||||
export const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
export const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
secp256k1.ProjectivePoint,
|
secp256k1.ProjectivePoint,
|
||||||
(scalars: bigint[]) => {
|
(scalars: bigint[]) => {
|
||||||
const { x, y } = mapSWU(Fp.create(scalars[0]));
|
const { x, y } = mapSWU(Fp.create(scalars[0]));
|
||||||
|
@ -1,18 +1,14 @@
|
|||||||
import { bls12_381 } from '../lib/esm/bls12-381.js';
|
|
||||||
import { describe, should } from 'micro-should';
|
|
||||||
import { deepStrictEqual, notDeepStrictEqual, throws } from 'assert';
|
import { deepStrictEqual, notDeepStrictEqual, throws } from 'assert';
|
||||||
import { sha512 } from '@noble/hashes/sha512';
|
|
||||||
import * as fc from 'fast-check';
|
import * as fc from 'fast-check';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
|
import { describe, should } from 'micro-should';
|
||||||
|
import { wNAF } from '../lib/esm/abstract/curve.js';
|
||||||
|
import { bytesToHex, utf8ToBytes } from '../lib/esm/abstract/utils.js';
|
||||||
|
import { hash_to_field } from '../lib/esm/abstract/hash-to-curve.js';
|
||||||
|
import { bls12_381 as bls } from '../lib/esm/bls12-381.js';
|
||||||
|
|
||||||
import zkVectors from './bls12-381/zkcrypto/converted.json' assert { type: 'json' };
|
import zkVectors from './bls12-381/zkcrypto/converted.json' assert { type: 'json' };
|
||||||
import pairingVectors from './bls12-381/go_pairing_vectors/pairing.json' assert { type: 'json' };
|
import pairingVectors from './bls12-381/go_pairing_vectors/pairing.json' assert { type: 'json' };
|
||||||
import { wNAF } from '../lib/esm/abstract/curve.js';
|
|
||||||
const bls = bls12_381;
|
|
||||||
const { Fp2 } = bls;
|
|
||||||
const G1Point = bls.G1.ProjectivePoint;
|
|
||||||
const G2Point = bls.G2.ProjectivePoint;
|
|
||||||
const G1Aff = (x, y) => G1Point.fromAffine({ x, y });
|
|
||||||
|
|
||||||
const G2_VECTORS = readFileSync('./test/bls12-381/bls12-381-g2-test-vectors.txt', 'utf-8')
|
const G2_VECTORS = readFileSync('./test/bls12-381/bls12-381-g2-test-vectors.txt', 'utf-8')
|
||||||
.trim()
|
.trim()
|
||||||
.split('\n')
|
.split('\n')
|
||||||
@ -28,7 +24,10 @@ const SCALAR_VECTORS = readFileSync('./test/bls12-381/bls12-381-scalar-test-vect
|
|||||||
const NUM_RUNS = Number(process.env.RUNS_COUNT || 10); // reduce to 1 to shorten test time
|
const NUM_RUNS = Number(process.env.RUNS_COUNT || 10); // reduce to 1 to shorten test time
|
||||||
fc.configureGlobal({ numRuns: NUM_RUNS });
|
fc.configureGlobal({ numRuns: NUM_RUNS });
|
||||||
|
|
||||||
// @ts-ignore
|
const { Fp2 } = bls;
|
||||||
|
const G1Point = bls.G1.ProjectivePoint;
|
||||||
|
const G2Point = bls.G2.ProjectivePoint;
|
||||||
|
const G1Aff = (x, y) => G1Point.fromAffine({ x, y });
|
||||||
const CURVE_ORDER = bls.CURVE.r;
|
const CURVE_ORDER = bls.CURVE.r;
|
||||||
|
|
||||||
const FC_MSG = fc.hexaString({ minLength: 64, maxLength: 64 });
|
const FC_MSG = fc.hexaString({ minLength: 64, maxLength: 64 });
|
||||||
@ -851,7 +850,7 @@ describe('bls12-381/basic', () => {
|
|||||||
for (let vector of G2_VECTORS) {
|
for (let vector of G2_VECTORS) {
|
||||||
const [priv, msg, expected] = vector;
|
const [priv, msg, expected] = vector;
|
||||||
const sig = bls.sign(msg, priv);
|
const sig = bls.sign(msg, priv);
|
||||||
deepStrictEqual(bls.utils.bytesToHex(sig), expected);
|
deepStrictEqual(bytesToHex(sig), expected);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
should(`produce correct scalars (${SCALAR_VECTORS.length} vectors)`, () => {
|
should(`produce correct scalars (${SCALAR_VECTORS.length} vectors)`, () => {
|
||||||
@ -863,8 +862,8 @@ describe('bls12-381/basic', () => {
|
|||||||
for (let vector of SCALAR_VECTORS) {
|
for (let vector of SCALAR_VECTORS) {
|
||||||
const [okmAscii, expectedHex] = vector;
|
const [okmAscii, expectedHex] = vector;
|
||||||
const expected = BigInt('0x' + expectedHex);
|
const expected = BigInt('0x' + expectedHex);
|
||||||
const okm = new Uint8Array(okmAscii.split('').map((c) => c.charCodeAt(0)));
|
const okm = utf8ToBytes(okmAscii);
|
||||||
const scalars = bls.utils.hashToField(okm, 1, options);
|
const scalars = hash_to_field(okm, 1, Object.assign({}, bls.CURVE.htfDefaults, options));
|
||||||
deepStrictEqual(scalars[0][0], expected);
|
deepStrictEqual(scalars[0][0], expected);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -973,25 +972,25 @@ describe('hash-to-curve', () => {
|
|||||||
// Point G1
|
// Point G1
|
||||||
const VECTORS_G1 = [
|
const VECTORS_G1 = [
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(''),
|
msg: utf8ToBytes(''),
|
||||||
expected:
|
expected:
|
||||||
'0576730ab036cbac1d95b38dca905586f28d0a59048db4e8778782d89bff856ddef89277ead5a21e2975c4a6e3d8c79e' +
|
'0576730ab036cbac1d95b38dca905586f28d0a59048db4e8778782d89bff856ddef89277ead5a21e2975c4a6e3d8c79e' +
|
||||||
'1273e568bebf1864393c517f999b87c1eaa1b8432f95aea8160cd981b5b05d8cd4a7cf00103b6ef87f728e4b547dd7ae',
|
'1273e568bebf1864393c517f999b87c1eaa1b8432f95aea8160cd981b5b05d8cd4a7cf00103b6ef87f728e4b547dd7ae',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abc'),
|
msg: utf8ToBytes('abc'),
|
||||||
expected:
|
expected:
|
||||||
'061daf0cc00d8912dac1d4cf5a7c32fca97f8b3bf3f805121888e5eb89f77f9a9f406569027ac6d0e61b1229f42c43d6' +
|
'061daf0cc00d8912dac1d4cf5a7c32fca97f8b3bf3f805121888e5eb89f77f9a9f406569027ac6d0e61b1229f42c43d6' +
|
||||||
'0de1601e5ba02cb637c1d35266f5700acee9850796dc88e860d022d7b9e7e3dce5950952e97861e5bb16d215c87f030d',
|
'0de1601e5ba02cb637c1d35266f5700acee9850796dc88e860d022d7b9e7e3dce5950952e97861e5bb16d215c87f030d',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abcdef0123456789'),
|
msg: utf8ToBytes('abcdef0123456789'),
|
||||||
expected:
|
expected:
|
||||||
'0fb3455436843e76079c7cf3dfef75e5a104dfe257a29a850c145568d500ad31ccfe79be9ae0ea31a722548070cf98cd' +
|
'0fb3455436843e76079c7cf3dfef75e5a104dfe257a29a850c145568d500ad31ccfe79be9ae0ea31a722548070cf98cd' +
|
||||||
'177989f7e2c751658df1b26943ee829d3ebcf131d8f805571712f3a7527ee5334ecff8a97fc2a50cea86f5e6212e9a57',
|
'177989f7e2c751658df1b26943ee829d3ebcf131d8f805571712f3a7527ee5334ecff8a97fc2a50cea86f5e6212e9a57',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(
|
msg: utf8ToBytes(
|
||||||
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||||
),
|
),
|
||||||
expected:
|
expected:
|
||||||
@ -1002,7 +1001,7 @@ describe('hash-to-curve', () => {
|
|||||||
for (let i = 0; i < VECTORS_G1.length; i++) {
|
for (let i = 0; i < VECTORS_G1.length; i++) {
|
||||||
const t = VECTORS_G1[i];
|
const t = VECTORS_G1[i];
|
||||||
should(`hashToCurve/G1 Killic (${i})`, () => {
|
should(`hashToCurve/G1 Killic (${i})`, () => {
|
||||||
const p = bls.hashToCurve.G1.hashToCurve(t.msg, {
|
const p = bls.G1.hashToCurve(t.msg, {
|
||||||
DST: 'BLS12381G1_XMD:SHA-256_SSWU_RO_TESTGEN',
|
DST: 'BLS12381G1_XMD:SHA-256_SSWU_RO_TESTGEN',
|
||||||
});
|
});
|
||||||
deepStrictEqual(p.toHex(false), t.expected);
|
deepStrictEqual(p.toHex(false), t.expected);
|
||||||
@ -1011,25 +1010,25 @@ describe('hash-to-curve', () => {
|
|||||||
|
|
||||||
const VECTORS_ENCODE_G1 = [
|
const VECTORS_ENCODE_G1 = [
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(''),
|
msg: utf8ToBytes(''),
|
||||||
expected:
|
expected:
|
||||||
'1223effdbb2d38152495a864d78eee14cb0992d89a241707abb03819a91a6d2fd65854ab9a69e9aacb0cbebfd490732c' +
|
'1223effdbb2d38152495a864d78eee14cb0992d89a241707abb03819a91a6d2fd65854ab9a69e9aacb0cbebfd490732c' +
|
||||||
'0f925d61e0b235ecd945cbf0309291878df0d06e5d80d6b84aa4ff3e00633b26f9a7cb3523ef737d90e6d71e8b98b2d5',
|
'0f925d61e0b235ecd945cbf0309291878df0d06e5d80d6b84aa4ff3e00633b26f9a7cb3523ef737d90e6d71e8b98b2d5',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abc'),
|
msg: utf8ToBytes('abc'),
|
||||||
expected:
|
expected:
|
||||||
'179d3fd0b4fb1da43aad06cea1fb3f828806ddb1b1fa9424b1e3944dfdbab6e763c42636404017da03099af0dcca0fd6' +
|
'179d3fd0b4fb1da43aad06cea1fb3f828806ddb1b1fa9424b1e3944dfdbab6e763c42636404017da03099af0dcca0fd6' +
|
||||||
'0d037cb1c6d495c0f5f22b061d23f1be3d7fe64d3c6820cfcd99b6b36fa69f7b4c1f4addba2ae7aa46fb25901ab483e4',
|
'0d037cb1c6d495c0f5f22b061d23f1be3d7fe64d3c6820cfcd99b6b36fa69f7b4c1f4addba2ae7aa46fb25901ab483e4',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abcdef0123456789'),
|
msg: utf8ToBytes('abcdef0123456789'),
|
||||||
expected:
|
expected:
|
||||||
'15aa66c77eded1209db694e8b1ba49daf8b686733afaa7b68c683d0b01788dfb0617a2e2d04c0856db4981921d3004af' +
|
'15aa66c77eded1209db694e8b1ba49daf8b686733afaa7b68c683d0b01788dfb0617a2e2d04c0856db4981921d3004af' +
|
||||||
'0952bb2f61739dd1d201dd0a79d74cda3285403d47655ee886afe860593a8a4e51c5b77a22d2133e3a4280eaaaa8b788',
|
'0952bb2f61739dd1d201dd0a79d74cda3285403d47655ee886afe860593a8a4e51c5b77a22d2133e3a4280eaaaa8b788',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(
|
msg: utf8ToBytes(
|
||||||
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||||
),
|
),
|
||||||
expected:
|
expected:
|
||||||
@ -1040,7 +1039,7 @@ describe('hash-to-curve', () => {
|
|||||||
for (let i = 0; i < VECTORS_ENCODE_G1.length; i++) {
|
for (let i = 0; i < VECTORS_ENCODE_G1.length; i++) {
|
||||||
const t = VECTORS_ENCODE_G1[i];
|
const t = VECTORS_ENCODE_G1[i];
|
||||||
should(`hashToCurve/G1 (Killic, encodeToCurve) (${i})`, () => {
|
should(`hashToCurve/G1 (Killic, encodeToCurve) (${i})`, () => {
|
||||||
const p = bls.hashToCurve.G1.encodeToCurve(t.msg, {
|
const p = bls.G1.encodeToCurve(t.msg, {
|
||||||
DST: 'BLS12381G1_XMD:SHA-256_SSWU_NU_TESTGEN',
|
DST: 'BLS12381G1_XMD:SHA-256_SSWU_NU_TESTGEN',
|
||||||
});
|
});
|
||||||
deepStrictEqual(p.toHex(false), t.expected);
|
deepStrictEqual(p.toHex(false), t.expected);
|
||||||
@ -1049,7 +1048,7 @@ describe('hash-to-curve', () => {
|
|||||||
// Point G2
|
// Point G2
|
||||||
const VECTORS_G2 = [
|
const VECTORS_G2 = [
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(''),
|
msg: utf8ToBytes(''),
|
||||||
expected:
|
expected:
|
||||||
'0fbdae26f9f9586a46d4b0b70390d09064ef2afe5c99348438a3c7d9756471e015cb534204c1b6824617a85024c772dc' +
|
'0fbdae26f9f9586a46d4b0b70390d09064ef2afe5c99348438a3c7d9756471e015cb534204c1b6824617a85024c772dc' +
|
||||||
'0a650bd36ae7455cb3fe5d8bb1310594551456f5c6593aec9ee0c03d2f6cb693bd2c5e99d4e23cbaec767609314f51d3' +
|
'0a650bd36ae7455cb3fe5d8bb1310594551456f5c6593aec9ee0c03d2f6cb693bd2c5e99d4e23cbaec767609314f51d3' +
|
||||||
@ -1057,7 +1056,7 @@ describe('hash-to-curve', () => {
|
|||||||
'0d8d49e7737d8f9fc5cef7c4b8817633103faf2613016cb86a1f3fc29968fe2413e232d9208d2d74a89bf7a48ac36f83',
|
'0d8d49e7737d8f9fc5cef7c4b8817633103faf2613016cb86a1f3fc29968fe2413e232d9208d2d74a89bf7a48ac36f83',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abc'),
|
msg: utf8ToBytes('abc'),
|
||||||
expected:
|
expected:
|
||||||
'03578447618463deb106b60e609c6f7cc446dc6035f84a72801ba17c94cd800583b493b948eff0033f09086fdd7f6175' +
|
'03578447618463deb106b60e609c6f7cc446dc6035f84a72801ba17c94cd800583b493b948eff0033f09086fdd7f6175' +
|
||||||
'1953ce6d4267939c7360756d9cca8eb34aac4633ef35369a7dc249445069888e7d1b3f9d2e75fbd468fbcbba7110ea02' +
|
'1953ce6d4267939c7360756d9cca8eb34aac4633ef35369a7dc249445069888e7d1b3f9d2e75fbd468fbcbba7110ea02' +
|
||||||
@ -1065,7 +1064,7 @@ describe('hash-to-curve', () => {
|
|||||||
'0882ab045b8fe4d7d557ebb59a63a35ac9f3d312581b509af0f8eaa2960cbc5e1e36bb969b6e22980b5cbdd0787fcf4e',
|
'0882ab045b8fe4d7d557ebb59a63a35ac9f3d312581b509af0f8eaa2960cbc5e1e36bb969b6e22980b5cbdd0787fcf4e',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abcdef0123456789'),
|
msg: utf8ToBytes('abcdef0123456789'),
|
||||||
expected:
|
expected:
|
||||||
'195fad48982e186ce3c5c82133aefc9b26d55979b6f530992a8849d4263ec5d57f7a181553c8799bcc83da44847bdc8d' +
|
'195fad48982e186ce3c5c82133aefc9b26d55979b6f530992a8849d4263ec5d57f7a181553c8799bcc83da44847bdc8d' +
|
||||||
'17b461fc3b96a30c2408958cbfa5f5927b6063a8ad199d5ebf2d7cdeffa9c20c85487204804fab53f950b2f87db365aa' +
|
'17b461fc3b96a30c2408958cbfa5f5927b6063a8ad199d5ebf2d7cdeffa9c20c85487204804fab53f950b2f87db365aa' +
|
||||||
@ -1073,7 +1072,7 @@ describe('hash-to-curve', () => {
|
|||||||
'174a3473a3af2d0302b9065e895ca4adba4ece6ce0b41148ba597001abb152f852dd9a96fb45c9de0a43d944746f833e',
|
'174a3473a3af2d0302b9065e895ca4adba4ece6ce0b41148ba597001abb152f852dd9a96fb45c9de0a43d944746f833e',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(
|
msg: utf8ToBytes(
|
||||||
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||||
),
|
),
|
||||||
expected:
|
expected:
|
||||||
@ -1086,7 +1085,7 @@ describe('hash-to-curve', () => {
|
|||||||
for (let i = 0; i < VECTORS_G2.length; i++) {
|
for (let i = 0; i < VECTORS_G2.length; i++) {
|
||||||
const t = VECTORS_G2[i];
|
const t = VECTORS_G2[i];
|
||||||
should(`hashToCurve/G2 Killic (${i})`, () => {
|
should(`hashToCurve/G2 Killic (${i})`, () => {
|
||||||
const p = bls.hashToCurve.G2.hashToCurve(t.msg, {
|
const p = bls.G2.hashToCurve(t.msg, {
|
||||||
DST: 'BLS12381G2_XMD:SHA-256_SSWU_RO_TESTGEN',
|
DST: 'BLS12381G2_XMD:SHA-256_SSWU_RO_TESTGEN',
|
||||||
});
|
});
|
||||||
deepStrictEqual(p.toHex(false), t.expected);
|
deepStrictEqual(p.toHex(false), t.expected);
|
||||||
@ -1095,7 +1094,7 @@ describe('hash-to-curve', () => {
|
|||||||
|
|
||||||
const VECTORS_ENCODE_G2 = [
|
const VECTORS_ENCODE_G2 = [
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(''),
|
msg: utf8ToBytes(''),
|
||||||
expected:
|
expected:
|
||||||
'0d4333b77becbf9f9dfa3ca928002233d1ecc854b1447e5a71f751c9042d000f42db91c1d6649a5e0ad22bd7bf7398b8' +
|
'0d4333b77becbf9f9dfa3ca928002233d1ecc854b1447e5a71f751c9042d000f42db91c1d6649a5e0ad22bd7bf7398b8' +
|
||||||
'027e4bfada0b47f9f07e04aec463c7371e68f2fd0c738cd517932ea3801a35acf09db018deda57387b0f270f7a219e4d' +
|
'027e4bfada0b47f9f07e04aec463c7371e68f2fd0c738cd517932ea3801a35acf09db018deda57387b0f270f7a219e4d' +
|
||||||
@ -1103,7 +1102,7 @@ describe('hash-to-curve', () => {
|
|||||||
'053674cba9ef516ddc218fedb37324e6c47de27f88ab7ef123b006127d738293c0277187f7e2f80a299a24d84ed03da7',
|
'053674cba9ef516ddc218fedb37324e6c47de27f88ab7ef123b006127d738293c0277187f7e2f80a299a24d84ed03da7',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abc'),
|
msg: utf8ToBytes('abc'),
|
||||||
expected:
|
expected:
|
||||||
'18f0f87b40af67c056915dbaf48534c592524e82c1c2b50c3734d02c0172c80df780a60b5683759298a3303c5d942778' +
|
'18f0f87b40af67c056915dbaf48534c592524e82c1c2b50c3734d02c0172c80df780a60b5683759298a3303c5d942778' +
|
||||||
'09349f1cb5b2e55489dcd45a38545343451cc30a1681c57acd4fb0a6db125f8352c09f4a67eb7d1d8242cb7d3405f97b' +
|
'09349f1cb5b2e55489dcd45a38545343451cc30a1681c57acd4fb0a6db125f8352c09f4a67eb7d1d8242cb7d3405f97b' +
|
||||||
@ -1111,7 +1110,7 @@ describe('hash-to-curve', () => {
|
|||||||
'02f2d9deb2c7742512f5b8230bf0fd83ea42279d7d39779543c1a43b61c885982b611f6a7a24b514995e8a098496b811',
|
'02f2d9deb2c7742512f5b8230bf0fd83ea42279d7d39779543c1a43b61c885982b611f6a7a24b514995e8a098496b811',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abcdef0123456789'),
|
msg: utf8ToBytes('abcdef0123456789'),
|
||||||
expected:
|
expected:
|
||||||
'19808ec5930a53c7cf5912ccce1cc33f1b3dcff24a53ce1cc4cba41fd6996dbed4843ccdd2eaf6a0cd801e562718d163' +
|
'19808ec5930a53c7cf5912ccce1cc33f1b3dcff24a53ce1cc4cba41fd6996dbed4843ccdd2eaf6a0cd801e562718d163' +
|
||||||
'149fe43777d34f0d25430dea463889bd9393bdfb4932946db23671727081c629ebb98a89604f3433fba1c67d356a4af7' +
|
'149fe43777d34f0d25430dea463889bd9393bdfb4932946db23671727081c629ebb98a89604f3433fba1c67d356a4af7' +
|
||||||
@ -1119,7 +1118,7 @@ describe('hash-to-curve', () => {
|
|||||||
'04c0d6793a766233b2982087b5f4a254f261003ccb3262ea7c50903eecef3e871d1502c293f9e063d7d293f6384f4551',
|
'04c0d6793a766233b2982087b5f4a254f261003ccb3262ea7c50903eecef3e871d1502c293f9e063d7d293f6384f4551',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(
|
msg: utf8ToBytes(
|
||||||
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||||
),
|
),
|
||||||
expected:
|
expected:
|
||||||
@ -1132,7 +1131,7 @@ describe('hash-to-curve', () => {
|
|||||||
for (let i = 0; i < VECTORS_ENCODE_G2.length; i++) {
|
for (let i = 0; i < VECTORS_ENCODE_G2.length; i++) {
|
||||||
const t = VECTORS_ENCODE_G2[i];
|
const t = VECTORS_ENCODE_G2[i];
|
||||||
should(`hashToCurve/G2 (Killic, encodeToCurve) (${i})`, () => {
|
should(`hashToCurve/G2 (Killic, encodeToCurve) (${i})`, () => {
|
||||||
const p = bls.hashToCurve.G2.encodeToCurve(t.msg, {
|
const p = bls.G2.encodeToCurve(t.msg, {
|
||||||
DST: 'BLS12381G2_XMD:SHA-256_SSWU_NU_TESTGEN',
|
DST: 'BLS12381G2_XMD:SHA-256_SSWU_NU_TESTGEN',
|
||||||
});
|
});
|
||||||
deepStrictEqual(p.toHex(false), t.expected);
|
deepStrictEqual(p.toHex(false), t.expected);
|
||||||
@ -1265,7 +1264,7 @@ describe('bls12-381 deterministic', () => {
|
|||||||
should('Killic based/Pairing', () => {
|
should('Killic based/Pairing', () => {
|
||||||
const t = bls.pairing(G1Point.BASE, G2Point.BASE);
|
const t = bls.pairing(G1Point.BASE, G2Point.BASE);
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
bls.utils.bytesToHex(Fp12.toBytes(t)),
|
bytesToHex(Fp12.toBytes(t)),
|
||||||
killicHex([
|
killicHex([
|
||||||
'0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631',
|
'0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631',
|
||||||
'04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef',
|
'04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef',
|
||||||
@ -1287,7 +1286,7 @@ describe('bls12-381 deterministic', () => {
|
|||||||
let p2 = G2Point.BASE;
|
let p2 = G2Point.BASE;
|
||||||
for (let v of pairingVectors) {
|
for (let v of pairingVectors) {
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
bls.utils.bytesToHex(Fp12.toBytes(bls.pairing(p1, p2))),
|
bytesToHex(Fp12.toBytes(bls.pairing(p1, p2))),
|
||||||
// Reverse order
|
// Reverse order
|
||||||
v.match(/.{96}/g).reverse().join('')
|
v.match(/.{96}/g).reverse().join('')
|
||||||
);
|
);
|
||||||
|
@ -12,11 +12,8 @@ import * as ed25519 from '../lib/esm/ed25519.js';
|
|||||||
import * as ed448 from '../lib/esm/ed448.js';
|
import * as ed448 from '../lib/esm/ed448.js';
|
||||||
import * as secp256k1 from '../lib/esm/secp256k1.js';
|
import * as secp256k1 from '../lib/esm/secp256k1.js';
|
||||||
import { bls12_381 } from '../lib/esm/bls12-381.js';
|
import { bls12_381 } from '../lib/esm/bls12-381.js';
|
||||||
import {
|
import { expand_message_xmd, expand_message_xof } from '../lib/esm/abstract/hash-to-curve.js';
|
||||||
stringToBytes,
|
import { utf8ToBytes } from '../lib/esm/abstract/utils.js';
|
||||||
expand_message_xmd,
|
|
||||||
expand_message_xof,
|
|
||||||
} from '../lib/esm/abstract/hash-to-curve.js';
|
|
||||||
// XMD
|
// XMD
|
||||||
import { default as xmd_sha256_38 } from './hash-to-curve/expand_message_xmd_SHA256_38.json' assert { type: 'json' };
|
import { default as xmd_sha256_38 } from './hash-to-curve/expand_message_xmd_SHA256_38.json' assert { type: 'json' };
|
||||||
import { default as xmd_sha256_256 } from './hash-to-curve/expand_message_xmd_SHA256_256.json' assert { type: 'json' };
|
import { default as xmd_sha256_256 } from './hash-to-curve/expand_message_xmd_SHA256_256.json' assert { type: 'json' };
|
||||||
@ -56,9 +53,9 @@ function testExpandXMD(hash, vectors) {
|
|||||||
const t = vectors.tests[i];
|
const t = vectors.tests[i];
|
||||||
should(`${vectors.hash}/${vectors.DST.length}/${i}`, () => {
|
should(`${vectors.hash}/${vectors.DST.length}/${i}`, () => {
|
||||||
const p = expand_message_xmd(
|
const p = expand_message_xmd(
|
||||||
stringToBytes(t.msg),
|
utf8ToBytes(t.msg),
|
||||||
stringToBytes(vectors.DST),
|
utf8ToBytes(vectors.DST),
|
||||||
t.len_in_bytes,
|
Number.parseInt(t.len_in_bytes),
|
||||||
hash
|
hash
|
||||||
);
|
);
|
||||||
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
|
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
|
||||||
@ -79,9 +76,9 @@ function testExpandXOF(hash, vectors) {
|
|||||||
const t = vectors.tests[i];
|
const t = vectors.tests[i];
|
||||||
should(`${i}`, () => {
|
should(`${i}`, () => {
|
||||||
const p = expand_message_xof(
|
const p = expand_message_xof(
|
||||||
stringToBytes(t.msg),
|
utf8ToBytes(t.msg),
|
||||||
stringToBytes(vectors.DST),
|
utf8ToBytes(vectors.DST),
|
||||||
+t.len_in_bytes,
|
Number.parseInt(t.len_in_bytes),
|
||||||
vectors.k,
|
vectors.k,
|
||||||
hash
|
hash
|
||||||
);
|
);
|
||||||
@ -112,7 +109,7 @@ function testCurve(curve, ro, nu) {
|
|||||||
const t = ro.vectors[i];
|
const t = ro.vectors[i];
|
||||||
should(`(${i})`, () => {
|
should(`(${i})`, () => {
|
||||||
const p = curve
|
const p = curve
|
||||||
.hashToCurve(stringToBytes(t.msg), {
|
.hashToCurve(utf8ToBytes(t.msg), {
|
||||||
DST: ro.dst,
|
DST: ro.dst,
|
||||||
})
|
})
|
||||||
.toAffine();
|
.toAffine();
|
||||||
@ -126,7 +123,7 @@ function testCurve(curve, ro, nu) {
|
|||||||
const t = nu.vectors[i];
|
const t = nu.vectors[i];
|
||||||
should(`(${i})`, () => {
|
should(`(${i})`, () => {
|
||||||
const p = curve
|
const p = curve
|
||||||
.encodeToCurve(stringToBytes(t.msg), {
|
.encodeToCurve(utf8ToBytes(t.msg), {
|
||||||
DST: nu.dst,
|
DST: nu.dst,
|
||||||
})
|
})
|
||||||
.toAffine();
|
.toAffine();
|
||||||
@ -140,8 +137,8 @@ function testCurve(curve, ro, nu) {
|
|||||||
testCurve(secp256r1, p256_ro, p256_nu);
|
testCurve(secp256r1, p256_ro, p256_nu);
|
||||||
testCurve(secp384r1, p384_ro, p384_nu);
|
testCurve(secp384r1, p384_ro, p384_nu);
|
||||||
testCurve(secp521r1, p521_ro, p521_nu);
|
testCurve(secp521r1, p521_ro, p521_nu);
|
||||||
testCurve(bls12_381.hashToCurve.G1, g1_ro, g1_nu);
|
testCurve(bls12_381.G1, g1_ro, g1_nu);
|
||||||
testCurve(bls12_381.hashToCurve.G2, g2_ro, g2_nu);
|
testCurve(bls12_381.G2, g2_ro, g2_nu);
|
||||||
testCurve(secp256k1, secp256k1_ro, secp256k1_nu);
|
testCurve(secp256k1, secp256k1_ro, secp256k1_nu);
|
||||||
testCurve(ed25519, ed25519_ro, ed25519_nu);
|
testCurve(ed25519, ed25519_ro, ed25519_nu);
|
||||||
testCurve(ed448, ed448_ro, ed448_nu);
|
testCurve(ed448, ed448_ro, ed448_nu);
|
||||||
|
Loading…
Reference in New Issue
Block a user