noble-xwing
Version:
Typescript implementation of the X-Wing hybrid Post Quantum KEM using the noble library, as outlined in https://eprint.iacr.org/2024/039.
43 lines • 2.05 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateKeyPair = generateKeyPair;
exports.encapsulate = encapsulate;
exports.decapsulate = decapsulate;
const ml_kem_1 = require("@noble/post-quantum/ml-kem");
const utils_1 = require("@noble/post-quantum/utils");
const sha3_1 = require("@noble/hashes/sha3");
const ed25519_1 = require("@noble/curves/ed25519");
function expandDecapsulationKey(seed) {
const expanded = (0, sha3_1.shake256)(seed, { dkLen: 96 });
const { publicKey: pkM, secretKey: skM } = ml_kem_1.ml_kem768.keygen(expanded.subarray(0, 64));
const skX = expanded.subarray(64, 96);
const pkX = ed25519_1.x25519.getPublicKey(skX);
return [skM, skX, pkM, pkX];
}
function generateKeyPair(seed = (0, utils_1.randomBytes)(32)) {
const [, , pkM, pkX] = expandDecapsulationKey(seed);
return { sk: seed, pk: new Uint8Array([...pkM, ...pkX]) };
}
const xWingLabel = [0x5c, 0x2e, 0x2f, 0x2f, 0x5e, 0x5c];
function combiner(ssM, ssX, ctX, pkX) {
return (0, sha3_1.sha3_256)(new Uint8Array([...ssM, ...ssX, ...ctX, ...pkX, ...xWingLabel]));
}
function encapsulate(publicKey, eseed = (0, utils_1.randomBytes)(64)) {
const pkM = publicKey.subarray(0, 1184);
const pkX = publicKey.subarray(1184, 1216);
const ekX = eseed.subarray(32, 64);
const ctX = ed25519_1.x25519.getPublicKey(ekX);
const ssX = ed25519_1.x25519.getSharedSecret(ekX, pkX);
const { cipherText: ctM, sharedSecret: ssM } = ml_kem_1.ml_kem768.encapsulate(pkM, eseed.subarray(0, 32));
const ss = combiner(ssM, ssX, ctX, pkX);
return { ss, ct: new Uint8Array([...ctM, ...ctX]) };
}
function decapsulate(cipherText, secretKey) {
const [skM, skX, , pkX] = expandDecapsulationKey(secretKey);
const ctM = cipherText.subarray(0, 1088);
const ctX = cipherText.subarray(1088, 1120);
const ssM = ml_kem_1.ml_kem768.decapsulate(ctM, skM);
const ssX = ed25519_1.x25519.getSharedSecret(skX, ctX);
return combiner(ssM, ssX, ctX, pkX);
}
//# sourceMappingURL=xwingSparse.js.map