mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-14 11:05:41 +05:00
enforce double signature
This commit is contained in:
parent
b454b003db
commit
3263216974
@ -77,47 +77,74 @@ Block.validateLoginBlock = function (Env, publicKey, signature, block, pqPublicK
|
||||
if (sigType === 1 && u8_signature.length > 65) {
|
||||
// Hybrid signature - check the classical part first
|
||||
const classicalSig = u8_signature.subarray(1, 1 + 64); // Ed25519 signature is 64 bytes
|
||||
verified = Nacl.sign.detached.verify(hash, classicalSig, u8_public_key);
|
||||
const classicalVerified = Nacl.sign.detached.verify(hash, classicalSig, u8_public_key);
|
||||
|
||||
// Check for PQ signature as well, but don't require it to pass
|
||||
if (verified && ml_kem && ml_dsa) {
|
||||
try {
|
||||
// Get PQ signature length from the 4 bytes after classical signature
|
||||
const pqSigLenView = new DataView(u8_signature.buffer, u8_signature.byteOffset + 65);
|
||||
const pqSigLen = pqSigLenView.getUint32(0, false); // big-endian
|
||||
if (!classicalVerified) {
|
||||
Env.Log.error('BLOCK_CLASSICAL_VERIFICATION_FAILED', {
|
||||
blockId: publicKey
|
||||
});
|
||||
return void cb('E_COULD_NOT_VERIFY_CLASSICAL');
|
||||
}
|
||||
|
||||
// Extract PQ signature
|
||||
const pqSig = u8_signature.subarray(1 + 64 + 4, 1 + 64 + 4 + pqSigLen);
|
||||
// Now check PQ signature - this is required for hybrid signatures
|
||||
let pqVerified = false;
|
||||
|
||||
// If PQ public key is provided, verify the PQ signature
|
||||
let publicKeyToUse = pqPublicKey;
|
||||
if (!publicKeyToUse && Env.blockInfo && Env.blockInfo[publicKey] && Env.blockInfo[publicKey].pqPublicKey) {
|
||||
publicKeyToUse = Env.blockInfo[publicKey].pqPublicKey;
|
||||
}
|
||||
if (!ml_kem || !ml_dsa) {
|
||||
Env.Log.error('BLOCK_PQ_VERIFICATION_ERROR', {
|
||||
error: 'PQ libraries not available',
|
||||
blockId: publicKey
|
||||
});
|
||||
return void cb('E_PQ_LIBRARIES_MISSING');
|
||||
}
|
||||
|
||||
if (publicKeyToUse) {
|
||||
const pqPublicKeyDecoded = Util.decodeBase64(publicKeyToUse);
|
||||
try {
|
||||
// Get PQ signature length from the 4 bytes after classical signature
|
||||
const pqSigLenView = new DataView(u8_signature.buffer, u8_signature.byteOffset + 65);
|
||||
const pqSigLen = pqSigLenView.getUint32(0, false); // big-endian
|
||||
|
||||
const pqVerified = ml_dsa.ml_dsa44.internal.verify(
|
||||
pqPublicKeyDecoded,
|
||||
hash,
|
||||
pqSig
|
||||
);
|
||||
// Extract PQ signature
|
||||
const pqSig = u8_signature.subarray(1 + 64 + 4, 1 + 64 + 4 + pqSigLen);
|
||||
|
||||
console.log("PQ verification result:", pqVerified);
|
||||
// If PQ public key is provided, verify the PQ signature
|
||||
let publicKeyToUse = pqPublicKey;
|
||||
if (!publicKeyToUse && Env.blockInfo && Env.blockInfo[publicKey] && Env.blockInfo[publicKey].pqPublicKey) {
|
||||
publicKeyToUse = Env.blockInfo[publicKey].pqPublicKey;
|
||||
}
|
||||
|
||||
Env.Log.info('BLOCK_PQ_VERIFICATION_RESULT', {
|
||||
blockId: publicKey,
|
||||
result: pqVerified
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
if (!publicKeyToUse) {
|
||||
Env.Log.error('BLOCK_PQ_VERIFICATION_ERROR', {
|
||||
error: err.message,
|
||||
error: 'PQ public key not available',
|
||||
blockId: publicKey
|
||||
});
|
||||
return void cb('E_MISSING_PQ_PUBLIC_KEY');
|
||||
}
|
||||
|
||||
const pqPublicKeyDecoded = Util.decodeBase64(publicKeyToUse);
|
||||
|
||||
pqVerified = ml_dsa.ml_dsa44.internal.verify(
|
||||
pqPublicKeyDecoded,
|
||||
hash,
|
||||
pqSig
|
||||
);
|
||||
|
||||
Env.Log.info('BLOCK_PQ_VERIFICATION_RESULT', {
|
||||
blockId: publicKey,
|
||||
result: pqVerified
|
||||
});
|
||||
|
||||
if (!pqVerified) {
|
||||
return void cb('E_COULD_NOT_VERIFY_PQ');
|
||||
}
|
||||
} catch (err) {
|
||||
Env.Log.error('BLOCK_PQ_VERIFICATION_ERROR', {
|
||||
error: err.message,
|
||||
blockId: publicKey
|
||||
});
|
||||
return void cb('E_PQ_VERIFICATION_ERROR');
|
||||
}
|
||||
|
||||
// Both classical and PQ signatures verified
|
||||
verified = classicalVerified && pqVerified;
|
||||
} else {
|
||||
// Classical signature or unrecognized format - use normal verification
|
||||
// For type 0 we need to skip the first byte
|
||||
@ -151,49 +178,81 @@ Block.validateAncestorProof = function (Env, proof, _cb) {
|
||||
if (sigType === 1 && u8_sig.length > 65) {
|
||||
// Hybrid signature - check the classical part first
|
||||
const classicalSig = u8_sig.subarray(1, 1 + 64); // Ed25519 signature is 64 bytes
|
||||
valid = Nacl.sign.detached.verify(u8_pub, classicalSig, u8_pub);
|
||||
const classicalVerified = Nacl.sign.detached.verify(u8_pub, classicalSig, u8_pub);
|
||||
|
||||
// Check for PQ signature as well, but don't require it to pass
|
||||
if (valid && ml_kem && ml_dsa) {
|
||||
try {
|
||||
// Get PQ signature length from the 4 bytes after classical signature
|
||||
const pqSigLenView = new DataView(u8_sig.buffer, u8_sig.byteOffset + 65);
|
||||
const pqSigLen = pqSigLenView.getUint32(0, false); // big-endian
|
||||
if (!classicalVerified) {
|
||||
Env.Log.error('ANCESTOR_CLASSICAL_VERIFICATION_FAILED', {
|
||||
blockId: pub
|
||||
});
|
||||
w.abort();
|
||||
return void cb('E_INVALID_ANCESTOR_PROOF_CLASSICAL');
|
||||
}
|
||||
|
||||
// Extract PQ signature
|
||||
const pqSig = u8_sig.subarray(1 + 64 + 4, 1 + 64 + 4 + pqSigLen);
|
||||
// Now check PQ signature - this is required for hybrid signatures
|
||||
let pqVerified = false;
|
||||
|
||||
// If PQ public key is provided, verify the PQ signature
|
||||
let pqPublicKey;
|
||||
if (Env.blockInfo && Env.blockInfo[pub] && Env.blockInfo[pub].pqPublicKey) {
|
||||
pqPublicKey = Env.blockInfo[pub].pqPublicKey;
|
||||
} else if (ancestorPqPublicKey) {
|
||||
pqPublicKey = ancestorPqPublicKey;
|
||||
}
|
||||
if (!ml_kem || !ml_dsa) {
|
||||
Env.Log.error('ANCESTOR_PQ_VERIFICATION_ERROR', {
|
||||
error: 'PQ libraries not available',
|
||||
blockId: pub
|
||||
});
|
||||
w.abort();
|
||||
return void cb('E_PQ_LIBRARIES_MISSING');
|
||||
}
|
||||
|
||||
if (pqPublicKey) {
|
||||
const pqPublicKeyDecoded = Util.decodeBase64(pqPublicKey);
|
||||
try {
|
||||
// Get PQ signature length from the 4 bytes after classical signature
|
||||
const pqSigLenView = new DataView(u8_sig.buffer, u8_sig.byteOffset + 65);
|
||||
const pqSigLen = pqSigLenView.getUint32(0, false); // big-endian
|
||||
|
||||
const pqVerified = ml_dsa.ml_dsa44.internal.verify(
|
||||
pqPublicKeyDecoded,
|
||||
u8_pub,
|
||||
pqSig
|
||||
);
|
||||
// Extract PQ signature
|
||||
const pqSig = u8_sig.subarray(1 + 64 + 4, 1 + 64 + 4 + pqSigLen);
|
||||
|
||||
console.log("PQ verification result 2:", pqVerified);
|
||||
// If PQ public key is provided, verify the PQ signature
|
||||
let pqPublicKey;
|
||||
if (Env.blockInfo && Env.blockInfo[pub] && Env.blockInfo[pub].pqPublicKey) {
|
||||
pqPublicKey = Env.blockInfo[pub].pqPublicKey;
|
||||
} else if (ancestorPqPublicKey) {
|
||||
pqPublicKey = ancestorPqPublicKey;
|
||||
}
|
||||
|
||||
Env.Log.info('ANCESTOR_PQ_VERIFICATION_RESULT', {
|
||||
blockId: pub,
|
||||
result: pqVerified
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
if (!pqPublicKey) {
|
||||
Env.Log.error('ANCESTOR_PQ_VERIFICATION_ERROR', {
|
||||
error: err.message,
|
||||
error: 'PQ public key not available',
|
||||
blockId: pub
|
||||
});
|
||||
w.abort();
|
||||
return void cb('E_MISSING_PQ_PUBLIC_KEY');
|
||||
}
|
||||
|
||||
const pqPublicKeyDecoded = Util.decodeBase64(pqPublicKey);
|
||||
|
||||
pqVerified = ml_dsa.ml_dsa44.internal.verify(
|
||||
pqPublicKeyDecoded,
|
||||
u8_pub,
|
||||
pqSig
|
||||
);
|
||||
|
||||
Env.Log.info('ANCESTOR_PQ_VERIFICATION_RESULT', {
|
||||
blockId: pub,
|
||||
result: pqVerified
|
||||
});
|
||||
|
||||
if (!pqVerified) {
|
||||
w.abort();
|
||||
return void cb('E_INVALID_ANCESTOR_PROOF_PQ');
|
||||
}
|
||||
} catch (err) {
|
||||
Env.Log.error('ANCESTOR_PQ_VERIFICATION_ERROR', {
|
||||
error: err.message,
|
||||
blockId: pub
|
||||
});
|
||||
w.abort();
|
||||
return void cb('E_PQ_VERIFICATION_ERROR');
|
||||
}
|
||||
|
||||
// Both classical and PQ signatures verified
|
||||
valid = classicalVerified && pqVerified;
|
||||
} else {
|
||||
// Classical signature or unrecognized format - use normal verification
|
||||
// For type 0 we need to skip the first byte
|
||||
|
||||
Loading…
Reference in New Issue
Block a user