utils, hash-to-curve: reduce code duplication

This commit is contained in:
Paul Miller 2024-02-27 22:24:15 +00:00
parent 6a85252dc3
commit 0ce103bd6b
No known key found for this signature in database
GPG Key ID: 697079DA6878B89B
2 changed files with 14 additions and 12 deletions

@ -2,7 +2,7 @@
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
import { mod, IField } from './modular.js';
import type { CHash } from './utils.js';
import { bytesToNumberBE, isBytes, concatBytes, utf8ToBytes, validateObject } from './utils.js';
import { bytesToNumberBE, abytes, isBytes, concatBytes, utf8ToBytes, validateObject } from './utils.js';
/**
* * `DST` is a domain separation tag, defined in section 2.2.5
@ -52,10 +52,8 @@ function strxor(a: Uint8Array, b: Uint8Array): Uint8Array {
return arr;
}
function abytes(item: unknown): void {
if (!isBytes(item)) throw new Error('Uint8Array expected');
}
function isNum(item: unknown): void {
function anum(item: unknown): void {
if (!Number.isSafeInteger(item)) throw new Error('number expected');
}
@ -69,7 +67,7 @@ export function expand_message_xmd(
): Uint8Array {
abytes(msg);
abytes(DST);
isNum(lenInBytes);
anum(lenInBytes);
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST));
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
@ -103,7 +101,7 @@ export function expand_message_xof(
): Uint8Array {
abytes(msg);
abytes(DST);
isNum(lenInBytes);
anum(lenInBytes);
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
if (DST.length > 255) {
@ -141,7 +139,7 @@ export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bi
});
const { p, k, m, hash, expand, DST: _DST } = options;
abytes(msg);
isNum(count);
anum(count);
const DST = validateDST(_DST);
const log2p = p.toString(2).length;
const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above

@ -23,6 +23,10 @@ export function isBytes(a: unknown): a is Uint8Array {
);
}
export function abytes(item: unknown): void {
if (!isBytes(item)) throw new Error('Uint8Array expected');
}
// Array where index 0xf0 (240) is mapped to string 'f0'
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>
i.toString(16).padStart(2, '0')
@ -31,7 +35,7 @@ const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
*/
export function bytesToHex(bytes: Uint8Array): string {
if (!isBytes(bytes)) throw new Error('Uint8Array expected');
abytes(bytes);
// pre-caching improves the speed 6x
let hex = '';
for (let i = 0; i < bytes.length; i++) {
@ -86,7 +90,7 @@ export function bytesToNumberBE(bytes: Uint8Array): bigint {
return hexToNumber(bytesToHex(bytes));
}
export function bytesToNumberLE(bytes: Uint8Array): bigint {
if (!isBytes(bytes)) throw new Error('Uint8Array expected');
abytes(bytes);
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
}
@ -138,7 +142,7 @@ export function concatBytes(...arrays: Uint8Array[]): Uint8Array {
let sum = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
if (!isBytes(a)) throw new Error('Uint8Array expected');
abytes(a);
sum += a.length;
}
const res = new Uint8Array(sum);
@ -194,7 +198,7 @@ export function bitGet(n: bigint, pos: number) {
/**
* Sets single bit at position.
*/
export const bitSet = (n: bigint, pos: number, value: boolean) => {
export function bitSet(n: bigint, pos: number, value: boolean) {
return n | ((value ? _1n : _0n) << BigInt(pos));
};