Skip to content

Commit

Permalink
Use ML-KEM instead of Kyber, implement message decryption
Browse files Browse the repository at this point in the history
  • Loading branch information
larabr committed Feb 27, 2024
1 parent 4f7b9da commit 88c121a
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 53 deletions.
42 changes: 8 additions & 34 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"bn.js": "^4.11.8",
"chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
"crystals-kyber-js": "^1.0.0",
"crystals-kyber-js": "larabr/crystals-kyber-js#e87c7319cbc56246a67fe94ff63b11bb421854ff",
"eslint": "^8.34.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-base": "^15.0.0",
Expand Down
7 changes: 4 additions & 3 deletions src/crypto/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ export async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, pri
case enums.publicKey.pqc_mlkem_x25519: {
const { eccPublicKey, mlkemPublicKey } = publicParams;
const { eccCipherText, mlkemCipherText, wrappedKey } = await publicKey.postQuantum.kem.encrypt(keyAlgo, eccPublicKey, mlkemPublicKey, data);
return { eccCipherText, mlkemCipherText, C: new ShortByteString(wrappedKey) };
const C = ECDHXSymmetricKey.fromObject({ algorithm: symmetricAlgo, wrappedKey });
return { eccCipherText, mlkemCipherText, C };
}
default:
return [];
Expand Down Expand Up @@ -168,7 +169,7 @@ export async function publicKeyDecrypt(keyAlgo, publicKeyParams, privateKeyParam
const { eccSecretKey, mlkemSecretKey } = privateKeyParams;
const { eccPublicKey } = publicKeyParams;
const { eccCipherText, mlkemCipherText, C } = sessionKeyParams;
return publicKey.postQuantum.kem.decrypt(keyAlgo, eccCipherText, mlkemCipherText, eccSecretKey, eccPublicKey, mlkemSecretKey, C.data);
return publicKey.postQuantum.kem.decrypt(keyAlgo, eccCipherText, mlkemCipherText, eccSecretKey, eccPublicKey, mlkemSecretKey, C.wrappedKey);
}
default:
throw new Error('Unknown public key encryption algorithm.');
Expand Down Expand Up @@ -392,7 +393,7 @@ export function parseEncSessionKeyParams(algo, bytes) {
case enums.publicKey.pqc_mlkem_x25519: {
const eccCipherText = util.readExactSubarray(bytes, read, read + getCurvePayloadSize(enums.publicKey.x25519)); read += eccCipherText.length;
const mlkemCipherText = util.readExactSubarray(bytes, read, read + 1088); read += mlkemCipherText.length;
const C = new ShortByteString(); read += C.read(bytes.subarray(read));
const C = new ECDHXSymmetricKey(); C.read(bytes.subarray(read));
return { eccCipherText, mlkemCipherText, C }; // eccCipherText || mlkemCipherText || len(C) || C
}
default:
Expand Down
5 changes: 4 additions & 1 deletion src/crypto/public_key/post_quantum/kem/kem.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,17 @@ async function multiKeyCombine(eccKeyShare, eccCipherText, mlkemKeyShare, mlkemC
// "OpenPGPCompositeKeyDerivationFunction"
// counter - the fixed 4 byte value 0x00000001
// customizationString - the UTF-8 encoding of the string "KDF"
if (outputBits !== 256) {
throw new Error('Unsupported output size');
}
const { kmac256 } = await import('@openpgp/noble-hashes/sha3-addons');
// const { eccKeyShare, eccCiphertext } = await publicKey.pqc.kem.ecdhX(keyAlgo, publicParams.A);
// const { keyShare: mlkemKeyShare, cipherText: mlkemCipherText } = await publicKey.pqc.kem.ml(keyAlgo, publicParams.publicKey);
const eccData = util.concatUint8Array([eccKeyShare, eccCipherText]); // eccKeyShare || eccCipherText
const mlkemData = util.concatUint8Array([mlkemKeyShare, mlkemCipherText]); //mlkemKeyShare || mlkemCipherText
// const fixedInfo = new Uint8Array([keyAlgo]);
const encData = util.concatUint8Array([
new Uint8Array([1, 0, 0, 0]),
new Uint8Array([0, 0, 0, 1]),
eccData,
mlkemData,
fixedInfo
Expand Down
12 changes: 6 additions & 6 deletions src/crypto/public_key/post_quantum/kem/ml_kem.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import enums from '../../../../enums';
export async function generate(algo) {
switch (algo) {
case enums.publicKey.pqc_mlkem_x25519: {
const { Kyber768 } = await import('crystals-kyber-js');
const kyberInstance = new Kyber768();
const { MlKem768 } = await import('crystals-kyber-js');

Check failure on line 6 in src/crypto/public_key/post_quantum/kem/ml_kem.js

View workflow job for this annotation

GitHub Actions / ESLint

Unable to resolve path to module 'crystals-kyber-js'
const kyberInstance = new MlKem768();
const [encapsulationKey, decapsulationKey] = await kyberInstance.generateKeyPair();

return { mlkemPublicKey: encapsulationKey, mlkemSecretKey: decapsulationKey };
Expand All @@ -17,8 +17,8 @@ export async function generate(algo) {
export async function encaps(algo, mlkemRecipientPublicKey) {
switch (algo) {
case enums.publicKey.pqc_mlkem_x25519: {
const { Kyber768 } = await import('crystals-kyber-js');
const kyberInstance = new Kyber768();
const { MlKem768 } = await import('crystals-kyber-js');

Check failure on line 20 in src/crypto/public_key/post_quantum/kem/ml_kem.js

View workflow job for this annotation

GitHub Actions / ESLint

Unable to resolve path to module 'crystals-kyber-js'
const kyberInstance = new MlKem768();
const [mlkemCipherText, mlkemKeyShare] = await kyberInstance.encap(mlkemRecipientPublicKey);

return { mlkemCipherText, mlkemKeyShare };
Expand All @@ -31,8 +31,8 @@ export async function encaps(algo, mlkemRecipientPublicKey) {
export async function decaps(algo, mlkemCipherText, mlkemSecretKey) {
switch (algo) {
case enums.publicKey.pqc_mlkem_x25519: {
const { Kyber768 } = await import('crystals-kyber-js');
const kyberInstance = new Kyber768();
const { MlKem768 } = await import('crystals-kyber-js');

Check failure on line 34 in src/crypto/public_key/post_quantum/kem/ml_kem.js

View workflow job for this annotation

GitHub Actions / ESLint

Unable to resolve path to module 'crystals-kyber-js'
const kyberInstance = new MlKem768();
const mlkemKeyShare = await kyberInstance.decap(mlkemCipherText, mlkemSecretKey);

return mlkemKeyShare;
Expand Down
2 changes: 1 addition & 1 deletion src/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export default {
/** Ed448 (Sign only) */
ed448: 28,
/** Post-quantum ML-KEM-768 + X25519 (Encrypt only) */
pqc_mlkem_x25519: 29,
pqc_mlkem_x25519: 105,
/** Post-quantum ML-DSA-64 + Ed25519 (Sign only) */
pqc_mldsa_ed25519: 35,

Expand Down
3 changes: 2 additions & 1 deletion src/key/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,8 @@ export function validateDecryptionKeyPacket(keyPacket, signature, config) {
case enums.publicKey.elgamal:
case enums.publicKey.ecdh:
case enums.publicKey.x25519:
case enums.publicKey.x448: {
case enums.publicKey.x448:
case enums.publicKey.pqc_mlkem_x25519: {
const isValidSigningKeyPacket = !signature.keyFlags || (signature.keyFlags[0] & enums.keyFlags.signData) !== 0;
if (isValidSigningKeyPacket && config.allowInsecureDecryptionWithSigningKeys) {
// This is only relevant for RSA keys, all other signing algorithms cannot decrypt
Expand Down
21 changes: 15 additions & 6 deletions src/packet/public_key_encrypted_session_key.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ class PublicKeyEncryptedSessionKeyPacket {
}
this.publicKeyAlgorithm = bytes[offset++];
this.encrypted = crypto.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(offset));
if (this.version === 3 && (
this.publicKeyAlgorithm === enums.publicKey.x25519 || this.publicKeyAlgorithm === enums.publicKey.x448)) {
if (hasCleartextCipherAlgo(this.version, this.publicKeyAlgorithm)) {
this.sessionKeyAlgorithm = enums.write(enums.symmetric, this.encrypted.C.algorithm);
}
}
Expand Down Expand Up @@ -201,10 +200,7 @@ class PublicKeyEncryptedSessionKeyPacket {

const { sessionKey, sessionKeyAlgorithm } = decodeSessionKey(this.version, this.publicKeyAlgorithm, decryptedData, randomSessionKey);

// v3 Montgomery curves have cleartext cipher algo
if (this.version === 3 && (
this.publicKeyAlgorithm !== enums.publicKey.x25519 && this.publicKeyAlgorithm !== enums.publicKey.x448)
) {
if (this.version === 3 && !hasCleartextCipherAlgo(this.version, this.publicKeyAlgorithm)) {
this.sessionKeyAlgorithm = sessionKeyAlgorithm;
}
this.sessionKey = sessionKey;
Expand All @@ -229,6 +225,7 @@ function encodeSessionKey(version, keyAlgo, cipherAlgo, sessionKeyData) {
]);
case enums.publicKey.x25519:
case enums.publicKey.x448:
case enums.publicKey.pqc_mlkem_x25519:
return sessionKeyData;
default:
throw new Error('Unsupported public key algorithm');
Expand Down Expand Up @@ -277,10 +274,22 @@ function decodeSessionKey(version, keyAlgo, decryptedData, randomSessionKey) {
}
case enums.publicKey.x25519:
case enums.publicKey.x448:
case enums.publicKey.pqc_mlkem_x25519:
return {
sessionKey: decryptedData
};
default:
throw new Error('Unsupported public key algorithm');
}
}

function hasCleartextCipherAlgo(version, publicKeyAlgo) {
switch (publicKeyAlgo) {
case enums.publicKey.x25519:
case enums.publicKey.x448:
case enums.publicKey.pqc_mlkem_x25519:
return version === 3;
default:
return false;
}
}
119 changes: 119 additions & 0 deletions test/crypto/postQuantum.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,125 @@ export default () => describe('PQC', function () {
expect(decryptedSessionKey).to.deep.equal(sessionKey.data);
});

it('ML-KEM + X25519 - Test vector', async function () {
const armoredMessage = `-----BEGIN PGP MESSAGE-----
wcPUA/qyFfu1TBzoaRaET03uDIyjNeUBk84Hj31jS8SkuW7T/fY78wQZOA89
MWj0RSoythNA9LJY7749Zlunxl896ws3tIfvy7FzMZ0/6kPEYvADZby9kwpv
X6Ia3DNAKlhiJfXM7oWXaPUQ/rZWnLm+eEnhmkXqE82Vz3nfml7h3k5LQJo6
f43LX2+euqHDMhdxpffMD1INkABN1Ttzth/ezQ2/5Uob/YvxT4lROGmBTl9g
ua9xFN2Wo4cMxe5XxLYy8QUp+kH5Q+EdPmW9HYFu3YA1xFEALstmx9xM2oRg
KA84QZUVxcBmQekHbFiXkYpGVaZwqa/3oDqTW2tQvqDucShWkwXBryDYrPqm
cSOCdbOlyWxWHRTamgvBy0351dnEVTT+pm9DYDkpmdb0ToBpPebC8sy/WHWV
mRLLkvUPe+IGkgL/1ehNMPVvEACRScV5GviYvs26NruofJMQXZ3BbxARcZ++
vOTVXl+kC7x+LbQOS4gAyN3RdfBSxrKPH2LBYI7Ccd1pUl/u0AnS6fksDT6n
ofECxwvkLks/CEmGyWaxNCfAVVAPz8S4g3f8jxhK4jtRWhD0PpY3MLCH3bug
JlYTzQm2J59NT9Knm+9PXSKny/5GVNOpfwFfWLgrK58y4Y5DfK0FVhEnLpwW
yqV49y4ujJEWp3Sd9NSCw+oIzi9XwHduj1JP7T+QZn3ED5uW596Q5+kHpiv1
njg4JRJ7xJK9wC51I47kUmkppo0Er04DUx/1hfXxOmitVcmzDeo8CwVJsin5
6ac9UPhYLHyTRy7do/cAfd5nxTNSUBI2DB903zbySaI3JGGgEzxOc0RmoHNF
Ku9ajrK9uBZrMMjT0tIbRD+oWiN4h1tYVrPJVZTLiWZGKaVr0PJCBN8rSI9x
Hx9/8Vapp9or0tN/XBTf4In0/gmO/Rr65/46Al8vkWrgcpY2TFuB8vdygUUc
rgboLHZejnWyUVO2+PbEhtbE2PM5sUBLCLK5U1xQphm72bwuwk2cxZihsk98
L81bhl8z9yDNwei0uQ2fru+Gpp+6cKfBad0eXcC9K8WFwKpsrueDau3U8aG9
gUqSFpAy9wVha/xagmdWYFSl1d4YtBanpGUhRrlD9iSRUhVJUhtwFAwqhpnE
/6KiJDpi43O9Mq1Re3YivAjR/PeuaWPzY9STqUZGnt9lQ4Wx9WlJw9FY8fU8
QivWGW7inxhoN/T1or1Wx2iKdK6Oe6ZHBtKDypy9fwtam0SOyT31DFdq3pop
RXPWnbhzPZxgzGs79a42fFZbTD6iz50FeuJYGfHx8ahHPQlPbemS4JhJ0BcF
dtt9pzfJ3tAwxfAnhGJrJUJ/MOba+32uhjFYiwaU7o7ur2ak1K0eqqN3kAW4
QwDQRpsJaMcO+JdpgSDVdYEkOMyFPLqf8sWUjjXUCVSrct9RI6T5QvUgsgdD
jE06bMep6ElLug6LonwnyjnaUbSgiKG1LoH1HN44ltX+sTiTcrQR0xyv4qDt
Jlswct6sjc0pCYRti9kpbvSKNkFIyao7JiXNo5lrJ5BSZLe9NlxLP6RP6yYl
KIuejZDSRAHCoPc7ma1tGPoVA8BaezF5gCdfaHla2hDaecWB83Ys0VzWCflp
q2MMqQ1h2UVunrMAQ/rYb8GQdkShXzPIF78mXeES
-----END PGP MESSAGE-----`;
const privateKey = await openpgp.readKey({ armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
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
=jowz
-----END PGP PRIVATE KEY BLOCK-----` });

const { data: decryptedData } = await openpgp.decrypt({
message: await openpgp.readMessage({ armoredMessage }),
decryptionKeys: privateKey
});
expect(decryptedData).to.equal('hello world\n');
});

it('ML-DSA + Ed25519 - Generate/sign/verify', async function () {
const digest = new Uint8Array(32).fill(1);
const hashAlgo = openpgp.enums.hash.sha256;
Expand Down

0 comments on commit 88c121a

Please sign in to comment.