@hpke/dhkem-x448
Version:
A Hybrid Public Key Encryption (HPKE) module extension for X448
88 lines (87 loc) • 3.69 kB
JavaScript
/**
* This file is based on noble-curves (https://github.com/paulmillr/noble-curves).
*
* noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com)
*
* The original file is located at:
* https://github.com/paulmillr/noble-curves/blob/b9d49d2b41d550571a0c5be443ecb62109fa3373/src/ed448.ts
*/
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "@hpke/common"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.x448 = void 0;
/**
* Edwards448 (not Ed448-Goldilocks) curve with following addons:
* - X448 ECDH
* - Decaf cofactor elimination
* - Elligator hash-to-group / point indistinguishability
* Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2
* @module
*/
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const common_1 = require("@hpke/common");
// edwards448 curve
// a = 1n
// d = Fp.neg(39081n)
// Finite field 2n**448n - 2n**224n - 1n
// Subgroup order
// 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
const ed448_CURVE_p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffn;
const _1n = 1n;
const _2n = 2n;
const _3n = 3n;
const _11n = 11n;
const _22n = 22n;
const _44n = 44n;
const _88n = 88n;
const _223n = 223n;
// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
// Used for efficient square root calculation.
// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1]
function ed448_pow_Pminus3div4(x) {
const P = ed448_CURVE_p;
const b2 = (x * x * x) % P;
const b3 = (b2 * b2 * x) % P;
const b6 = ((0, common_1.pow2)(b3, _3n, P) * b3) % P;
const b9 = ((0, common_1.pow2)(b6, _3n, P) * b3) % P;
const b11 = ((0, common_1.pow2)(b9, _2n, P) * b2) % P;
const b22 = ((0, common_1.pow2)(b11, _11n, P) * b11) % P;
const b44 = ((0, common_1.pow2)(b22, _22n, P) * b22) % P;
const b88 = ((0, common_1.pow2)(b44, _44n, P) * b44) % P;
const b176 = ((0, common_1.pow2)(b88, _88n, P) * b88) % P;
const b220 = ((0, common_1.pow2)(b176, _44n, P) * b44) % P;
const b222 = ((0, common_1.pow2)(b220, _2n, P) * b2) % P;
const b223 = ((0, common_1.pow2)(b222, _1n, P) * x) % P;
return ((0, common_1.pow2)(b223, _223n, P) * b222) % P;
}
function adjustScalarBytes(bytes) {
// Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0,
bytes[0] &= 252; // 0b11111100
// and the most significant bit of the last byte to 1.
bytes[55] |= 128; // 0b10000000
// NOTE: is NOOP for 56 bytes scalars (X25519/X448)
bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
return bytes;
}
exports.x448 = (() => {
const P = ed448_CURVE_p;
return (0, common_1.montgomery)({
P,
type: "x448",
powPminus2: (x) => {
const Pminus3div4 = ed448_pow_Pminus3div4(x);
const Pminus3 = (0, common_1.pow2)(Pminus3div4, _2n, P);
return (0, common_1.mod)(Pminus3 * x, P); // Pminus3 * x = Pminus2
},
adjustScalarBytes,
});
})();
});