debug: add diagnostic logging to 3DES S/MIME decrypt path

Log legacy key import success/failure, CMS algorithm OIDs (content
encryption + key transport), legacy key availability during decrypt
attempts, and detailed error messages from both RSA-OAEP and
RSAES-PKCS1-v1_5 decrypt paths.
This commit is contained in:
Linus Rath
2026-03-30 19:15:02 +02:00
parent 92fb9bf132
commit 066ab1bc32
3 changed files with 29 additions and 5 deletions
+6 -1
View File
@@ -1546,7 +1546,12 @@ export function EmailViewer({
if (detection.type === 'enveloped-data') {
// Encrypted message
const { keyRecords, unlockedDecryptionKeys, unlockedLegacyDecryptionKeys } = smimeStore;
smimeDebug('[S/MIME] decrypt attempt:', { keyRecordCount: keyRecords.length, unlockedKeyCount: unlockedDecryptionKeys.size, keyRecordIds: keyRecords.map(k => k.id) });
smimeDebug('[S/MIME] decrypt attempt:', {
keyRecordCount: keyRecords.length,
unlockedKeyCount: unlockedDecryptionKeys.size,
legacyKeyCount: unlockedLegacyDecryptionKeys.size,
keyRecordIds: keyRecords.map(k => k.id),
});
// Short-circuit: no keys imported at all
if (keyRecords.length === 0) {
+6 -2
View File
@@ -298,8 +298,12 @@ export async function unlockPrivateKey(
false,
['decrypt'],
);
} catch {
// webcrypto-liner may not be available or key format unsupported
console.debug('[S/MIME] legacy RSAES-PKCS1-v1_5 key imported successfully:', {
algorithm: legacyDecryptionKey.algorithm,
usages: legacyDecryptionKey.usages,
});
} catch (err) {
console.warn('[S/MIME] legacy RSAES-PKCS1-v1_5 key import failed:', err);
}
}
+17 -2
View File
@@ -42,6 +42,18 @@ export async function smimeDecrypt(input: DecryptionInput): Promise<DecryptionRe
const contentInfo = parseContentInfo(cmsBytes);
const envelopedData = extractEnvelopedData(contentInfo);
// Log CMS algorithm details for diagnostics
const contentEncOid = envelopedData.encryptedContentInfo?.contentEncryptionAlgorithm?.algorithmId;
const recipientAlgs = envelopedData.recipientInfos?.map((ri) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(ri as any).value?.keyEncryptionAlgorithm?.algorithmId as string | undefined,
);
console.debug('[S/MIME] CMS algorithms:', {
contentEncryption: contentEncOid,
keyTransport: recipientAlgs,
legacyKeysAvailable: legacyUnlockedKeys?.size ?? 0,
});
// Find matching key records
const matchedRecords = findMatchingKeyRecords(envelopedData, keyRecords);
@@ -75,9 +87,11 @@ export async function smimeDecrypt(input: DecryptionInput): Promise<DecryptionRe
mimeBytes: new Uint8Array(decrypted),
keyRecordId: keyRecord.id,
};
} catch {
} catch (oaepError) {
// RSA-OAEP key didn't work, try legacy RSAES-PKCS1-v1_5 key
console.debug('[S/MIME] RSA-OAEP decrypt failed:', oaepError instanceof Error ? oaepError.message : oaepError);
const legacyKey = legacyUnlockedKeys?.get(keyRecord.id);
console.debug('[S/MIME] legacy key available:', !!legacyKey, legacyKey ? { algorithm: (legacyKey as CryptoKey).algorithm } : undefined);
if (legacyKey) {
try {
const decrypted = await decryptWithKey(envelopedData, recipientIndex, legacyKey, keyRecord);
@@ -85,8 +99,9 @@ export async function smimeDecrypt(input: DecryptionInput): Promise<DecryptionRe
mimeBytes: new Uint8Array(decrypted),
keyRecordId: keyRecord.id,
};
} catch {
} catch (legacyError) {
// Legacy key also didn't work, try the next record
console.debug('[S/MIME] RSAES-PKCS1-v1_5 decrypt also failed:', legacyError instanceof Error ? legacyError.message : legacyError);
}
}
continue;