Fix x448 private keys: must be 56 bytes, not 57. Reported by @larabr

This commit is contained in:
Paul Miller 2023-10-02 23:15:43 +00:00
parent 4752ab1f1e
commit 2da6abb336
No known key found for this signature in database
GPG Key ID: 697079DA6878B89B
2 changed files with 5 additions and 7 deletions

@ -150,17 +150,15 @@ export function montgomery(curveDef: CurveType): CurveFn {
function decodeUCoordinate(uEnc: Hex): bigint { function decodeUCoordinate(uEnc: Hex): bigint {
// Section 5: When receiving such an array, implementations of X25519 // Section 5: When receiving such an array, implementations of X25519
// 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
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
const u = ensureBytes('u coordinate', uEnc, montgomeryBytes); const u = ensureBytes('u coordinate', uEnc, montgomeryBytes);
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index) if (fieldLen === 32) u[31] &= 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('scalar', n); const bytes = ensureBytes('scalar', n);
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen) const len = bytes.length;
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`); if (len !== montgomeryBytes && len !== fieldLen)
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${len}`);
return bytesToNumberLE(adjustScalarBytes(bytes)); return bytesToNumberLE(adjustScalarBytes(bytes));
} }
function scalarMult(scalar: Hex, u: Hex): Uint8Array { function scalarMult(scalar: Hex, u: Hex): Uint8Array {

@ -140,7 +140,7 @@ export const x448 = /* @__PURE__ */ (() =>
a: BigInt(156326), a: BigInt(156326),
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
montgomeryBits: 448, montgomeryBits: 448,
nByteLength: 57, nByteLength: 56,
P: ed448P, P: ed448P,
Gu: BigInt(5), Gu: BigInt(5),
powPminus2: (x: bigint): bigint => { powPminus2: (x: bigint): bigint => {