Skip to content

Commit

Permalink
Switch to seed format for ML-DSA private key, update test vectors (dr…
Browse files Browse the repository at this point in the history
…aft 5)
  • Loading branch information
larabr committed Nov 14, 2024
1 parent 3604587 commit 7b83379
Show file tree
Hide file tree
Showing 5 changed files with 1,115 additions and 1,144 deletions.
16 changes: 9 additions & 7 deletions src/crypto/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,9 @@ export async function parsePrivateKeyParams(algo, bytes, publicParams) {
}
case enums.publicKey.pqc_mldsa_ed25519: {
const eccSecretKey = util.readExactSubarray(bytes, read, read + getCurvePayloadSize(enums.publicKey.ed25519)); read += eccSecretKey.length;
const mldsaSecretKey = util.readExactSubarray(bytes, read, read + 4032); read += mldsaSecretKey.length;
return { read, privateParams: { eccSecretKey, mldsaSecretKey } };
const mldsaSeed = util.readExactSubarray(bytes, read, read + 32); read += mldsaSeed.length;
const { mldsaSecretKey } = await publicKey.postQuantum.signature.mldsaExpandSecretSeed(algo, mldsaSeed);
return { read, privateParams: { eccSecretKey, mldsaSecretKey, mldsaSeed } };
}
default:
throw new UnsupportedError('Unknown public key encryption algorithm.');
Expand Down Expand Up @@ -428,7 +429,8 @@ export function serializeParams(algo, params) {
]);

const excludedFields = {
[enums.publicKey.pqc_mlkem_x25519]: new Set(['mlkemSecretKey']) // only `mlkemSeed` is serialized
[enums.publicKey.pqc_mlkem_x25519]: new Set(['mlkemSecretKey']), // only `mlkemSeed` is serialized
[enums.publicKey.pqc_mldsa_ed25519]: new Set(['mldsaSecretKey']) // only `mldsaSeed` is serialized
};

const orderedParams = Object.keys(params).map(name => {
Expand Down Expand Up @@ -506,8 +508,8 @@ export async function generateParams(algo, bits, oid, symmetric) {
publicParams: { eccPublicKey, mlkemPublicKey }
}));
case enums.publicKey.pqc_mldsa_ed25519:
return publicKey.postQuantum.signature.generate(algo).then(({ eccSecretKey, eccPublicKey, mldsaSecretKey, mldsaPublicKey }) => ({
privateParams: { eccSecretKey, mldsaSecretKey },
return publicKey.postQuantum.signature.generate(algo).then(({ eccSecretKey, eccPublicKey, mldsaSeed, mldsaSecretKey, mldsaPublicKey }) => ({
privateParams: { eccSecretKey, mldsaSeed, mldsaSecretKey },
publicParams: { eccPublicKey, mldsaPublicKey }
}));
case enums.publicKey.dsa:
Expand Down Expand Up @@ -607,9 +609,9 @@ export async function validateParams(algo, publicParams, privateParams) {
return publicKey.postQuantum.kem.validateParams(algo, eccPublicKey, eccSecretKey, mlkemPublicKey, mlkemSeed);
}
case enums.publicKey.pqc_mldsa_ed25519: {
const { eccSecretKey, mldsaSecretKey } = privateParams;
const { eccSecretKey, mldsaSeed } = privateParams;
const { eccPublicKey, mldsaPublicKey } = publicParams;
return publicKey.postQuantum.signature.validateParams(algo, eccPublicKey, eccSecretKey, mldsaPublicKey, mldsaSecretKey);
return publicKey.postQuantum.signature.validateParams(algo, eccPublicKey, eccSecretKey, mldsaPublicKey, mldsaSeed);
}
default:
throw new Error('Unknown public key algorithm.');
Expand Down
1 change: 1 addition & 0 deletions src/crypto/public_key/post_quantum/signature/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { generate, sign, verify, validateParams } from './signature';
export { expandSecretSeed as mldsaExpandSecretSeed } from './ml_dsa';
32 changes: 24 additions & 8 deletions src/crypto/public_key/post_quantum/signature/ml_dsa.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
import enums from '../../../../enums';
import util from '../../../../util';
import hash from '../../../hash';
import { getRandomBytes } from '../../../random';

export async function generate(algo) {
switch (algo) {
case enums.publicKey.pqc_mldsa_ed25519: {
const mldsaSeed = getRandomBytes(32);
const { mldsaSecretKey, mldsaPublicKey } = await expandSecretSeed(algo, mldsaSeed);

return { mldsaSeed, mldsaSecretKey, mldsaPublicKey };
}
default:
throw new Error('Unsupported signature algorithm');
}
}

/**
* Expand ML-DSA secret seed and retrieve the secret and public key material
* @param {module:enums.publicKey} algo - Public key algorithm
* @param {Uint8Array} seed - secret seed to expand
* @returns {Promise<{ mldsaPublicKey: Uint8Array, mldsaSecretKey: Uint8Array }>}
*/
export async function expandSecretSeed(algo, seed) {
switch (algo) {
case enums.publicKey.pqc_mldsa_ed25519: {
const { ml_dsa65 } = await import('@noble/post-quantum/ml-dsa');
const { secretKey: mldsaSecretKey, publicKey: mldsaPublicKey } = ml_dsa65.keygen();
const { secretKey: mldsaSecretKey, publicKey: mldsaPublicKey } = ml_dsa65.keygen(seed);

return { mldsaSecretKey, mldsaPublicKey };
}
default:
Expand Down Expand Up @@ -40,14 +59,11 @@ export async function verify(algo, mldsaPublicKey, dataDigest, mldsaSignature) {
}
}

export async function validateParams(algo, mldsaPublicKey, mldsaSecretKey) {
export async function validateParams(algo, mldsaPublicKey, mldsaSeed) {
switch (algo) {
case enums.publicKey.pqc_mldsa_ed25519: {
const message = getRandomBytes(8);
const hashAlgo = enums.hash.sha256;
const hashed = await hash.digest(hashAlgo, message);
const { mldsaSignature } = await sign(algo, mldsaSecretKey, hashed);
return verify(algo, mldsaPublicKey, hashed, mldsaSignature);
const { mldsaPublicKey: expectedPublicKey } = await expandSecretSeed(algo, mldsaSeed);
return util.equalsUint8Array(mldsaPublicKey, expectedPublicKey);
}
default:
throw new Error('Unsupported signature algorithm');
Expand Down
8 changes: 4 additions & 4 deletions src/crypto/public_key/post_quantum/signature/signature.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export async function generate(algo) {
switch (algo) {
case enums.publicKey.pqc_mldsa_ed25519: {
const { eccSecretKey, eccPublicKey } = await eccdsa.generate(algo);
const { mldsaSecretKey, mldsaPublicKey } = await mldsa.generate(algo);
return { eccSecretKey, eccPublicKey, mldsaSecretKey, mldsaPublicKey };
const { mldsaSeed, mldsaSecretKey, mldsaPublicKey } = await mldsa.generate(algo);
return { eccSecretKey, eccPublicKey, mldsaSeed, mldsaSecretKey, mldsaPublicKey };
}
default:
throw new Error('Unsupported signature algorithm');
Expand Down Expand Up @@ -40,9 +40,9 @@ export async function verify(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicK
}
}

export async function validateParams(algo, eccPublicKey, eccSecretKey, mldsaPublicKey, mldsaSecretKey) {
export async function validateParams(algo, eccPublicKey, eccSecretKey, mldsaPublicKey, mldsaSeed) {
const eccValidationPromise = eccdsa.validateParams(algo, eccPublicKey, eccSecretKey);
const mldsaValidationPromise = mldsa.validateParams(algo, mldsaPublicKey, mldsaSecretKey);
const mldsaValidationPromise = mldsa.validateParams(algo, mldsaPublicKey, mldsaSeed);
const valid = await eccValidationPromise && await mldsaValidationPromise;
return valid;
}
Loading

0 comments on commit 7b83379

Please sign in to comment.