diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index 6d0d185e3c..f99b89bbef 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -596,8 +596,11 @@ export async function validateParams(algo, publicParams, privateParams) { const { eccPublicKey, mlkemPublicKey } = publicParams; return publicKey.postQuantum.kem.validateParams(algo, eccPublicKey, eccSecretKey, mlkemPublicKey, mlkemSecretKey); } - case enums.publicKey.pqc_mldsa_ed25519: - throw new Error('TODO'); + case enums.publicKey.pqc_mldsa_ed25519: { + const { eccSecretKey, mldsaSecretKey } = privateParams; + const { eccPublicKey, mldsaPublicKey } = publicParams; + return publicKey.postQuantum.signature.validateParams(algo, eccPublicKey, eccSecretKey, mldsaPublicKey, mldsaSecretKey); + } default: throw new Error('Unknown public key algorithm.'); } diff --git a/src/crypto/public_key/post_quantum/signature/ecc_dsa.js b/src/crypto/public_key/post_quantum/signature/ecc_dsa.js index 59e0f0e103..4d7747e8f0 100644 --- a/src/crypto/public_key/post_quantum/signature/ecc_dsa.js +++ b/src/crypto/public_key/post_quantum/signature/ecc_dsa.js @@ -38,3 +38,12 @@ export async function verify(signatureAlgo, hashAlgo, eccPublicKey, dataDigest, throw new Error('Unsupported signature algorithm'); } } + +export async function validateParams(algo, eccPublicKey, eccSecretKey) { + switch (algo) { + case enums.publicKey.pqc_mldsa_ed25519: + return eddsa.validateParams(enums.publicKey.ed25519, eccPublicKey, eccSecretKey); + default: + throw new Error('Unsupported signature algorithm'); + } +} diff --git a/src/crypto/public_key/post_quantum/signature/index.js b/src/crypto/public_key/post_quantum/signature/index.js index 190945ecb5..1350e87d46 100644 --- a/src/crypto/public_key/post_quantum/signature/index.js +++ b/src/crypto/public_key/post_quantum/signature/index.js @@ -1 +1 @@ -export { generate, sign, verify } from './signature'; +export { generate, sign, verify, validateParams } from './signature'; diff --git a/src/crypto/public_key/post_quantum/signature/ml_dsa.js b/src/crypto/public_key/post_quantum/signature/ml_dsa.js index 9ec6ef80ed..09dc40aaa0 100644 --- a/src/crypto/public_key/post_quantum/signature/ml_dsa.js +++ b/src/crypto/public_key/post_quantum/signature/ml_dsa.js @@ -1,4 +1,6 @@ import enums from '../../../../enums'; +import hash from '../../../hash'; +import { getRandomBytes } from '../../../random'; export async function generate(algo) { switch (algo) { @@ -34,3 +36,17 @@ export async function verify(algo, mldsaPublicKey, dataDigest, mldsaSignature) { throw new Error('Unsupported signature algorithm'); } } + +export async function validateParams(algo, mldsaPublicKey, mldsaSecretKey) { + 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); + } + default: + throw new Error('Unsupported signature algorithm'); + } +} diff --git a/src/crypto/public_key/post_quantum/signature/signature.js b/src/crypto/public_key/post_quantum/signature/signature.js index a72c9f9dba..03ba34b4c6 100644 --- a/src/crypto/public_key/post_quantum/signature/signature.js +++ b/src/crypto/public_key/post_quantum/signature/signature.js @@ -39,3 +39,10 @@ export async function verify(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicK throw new Error('Unsupported signature algorithm'); } } + +export async function validateParams(algo, eccPublicKey, eccSecretKey, mldsaPublicKey, mldsaSecretKey) { + const eccValidationPromise = eccdsa.validateParams(algo, eccPublicKey, eccSecretKey); + const mldsaValidationPromise = mldsa.validateParams(algo, mldsaPublicKey, mldsaSecretKey); + const valid = await eccValidationPromise && await mldsaValidationPromise; + return valid; +} diff --git a/test/crypto/validate.js b/test/crypto/validate.js index fde15d3eaf..8881e45a36 100644 --- a/test/crypto/validate.js +++ b/test/crypto/validate.js @@ -315,31 +315,41 @@ export default () => { }); describe('PQC parameter validation', function() { + let pqcSigningKey; let pqcEncryptionSubkey; before(async () => { - const key = await generatePrivateKeyObject({ type: 'symmetric', subkeys: [{ type: 'pqc' }] }); - pqcEncryptionSubkey = key.subkeys[0]; + pqcSigningKey = await generatePrivateKeyObject({ type: 'pqc' }); + pqcEncryptionSubkey = pqcSigningKey.subkeys[0]; }); - async function cloneSubeyPacket(subkey) { - const subkeyPacket = new openpgp.SecretSubkeyPacket(); - await subkeyPacket.read(subkey.keyPacket.write()); - return subkeyPacket; - } - it('generated params are valid', async function() { + await expect(pqcSigningKey.keyPacket.validate()).to.not.be.rejected; await expect(pqcEncryptionSubkey.keyPacket.validate()).to.not.be.rejected; }); it('detect invalid ML-KEM public key part', async function() { - const keyPacket = await cloneSubeyPacket(pqcEncryptionSubkey); + const keyPacket = await cloneKeyPacket(pqcEncryptionSubkey); const { mlkemPublicKey } = keyPacket.publicParams; mlkemPublicKey[0]++; await expect(keyPacket.validate()).to.be.rejectedWith('Key is invalid'); }); it('detect invalid ECC-KEM key part', async function() { - const keyPacket = await cloneSubeyPacket(pqcEncryptionSubkey); + const keyPacket = await cloneKeyPacket(pqcEncryptionSubkey); + const { eccPublicKey } = keyPacket.publicParams; + eccPublicKey[0]++; + await expect(keyPacket.validate()).to.be.rejectedWith('Key is invalid'); + }); + + it('detect invalid ML-DSA public key part', async function() { + const keyPacket = await cloneKeyPacket(pqcSigningKey); + const { mldsaPublicKey } = keyPacket.publicParams; + mldsaPublicKey[0]++; + await expect(keyPacket.validate()).to.be.rejectedWith('Key is invalid'); + }); + + it('detect invalid ECC part', async function() { + const keyPacket = await cloneKeyPacket(pqcSigningKey); const { eccPublicKey } = keyPacket.publicParams; eccPublicKey[0]++; await expect(keyPacket.validate()).to.be.rejectedWith('Key is invalid');