Node.js用OpenPGP私钥解密报错‘未找到解密密钥包’求助
Node.js openpgp库解密失败:
No decryption key packets found 及GPG警告处理 问题场景
在Node.js中使用openpgp库解密OpenPGP加密消息时失败,报错:
Decryption failed completely. Error details:
Error decrypting message: No decryption key packets found
加密消息由密钥7851C0CAFDBF2903(RSA 2048)加密,持有对应未加密私钥,但GPG命令行手动解密可成功,同时出现以下警告:
gpg: encrypted with rsa2048 key, ID 7851C0CAFDBF2903, created 2024-10-22 gpg: used key is not marked for encryption use. gpg: WARNING: cipher algorithm CAST5 not found in recipient preferences
使用的解密代码:
const fs = require('fs'); const openpgp = require('openpgp'); async function decryptFile(encryptedFilePath, privateKeyFilePath, passphrase, outputFilePath) { try { const encryptedData = fs.readFileSync(encryptedFilePath, 'utf8'); const privateKeyArmored = fs.readFileSync(privateKeyFilePath, 'utf8'); // Parse the private key const privateKey = await openpgp.readKey({ armoredKey: privateKeyArmored }); console.log('Private key fingerprint:', privateKey.getFingerprint()); // Decrypt the private key if necessary let decryptedPrivateKey = privateKey; if (privateKey.isEncrypted) { decryptedPrivateKey = await openpgp.decryptKey({ privateKey, passphrase }); } const message = await openpgp.readMessage({ armoredMessage: encryptedData }); const { data: decryptedData } = await openpgp.decrypt({ message, decryptionKeys: decryptedPrivateKey, format: 'utf8' }); // Ensure output directory exists const outputDir = outputFilePath.substring(0, outputFilePath.lastIndexOf('/')); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } fs.writeFileSync(outputFilePath, decryptedData, 'utf8'); console.log('Decryption successful! File saved to:', outputFilePath); } catch (error) { console.error('Decryption failed:', error.message); throw error; } } async function main() { const encryptedFilePath = './Testd/Trade_21112024.asc'; const privateKeyFilePath = './key/private.key'; const passphrase = ''; const outputFilePath = './output/Trade_21112024.csv'; try { await decryptFile(encryptedFilePath, privateKeyFilePath, passphrase, outputFilePath); } catch (error) { console.error('Program failed:', error.message); } } main();
核心问题:
- 持有对应私钥,但openpgp库报错
No decryption key packets found - GPG手动解密成功,但提示密钥未标记加密用途、CAST5算法不在收件人偏好中
已尝试操作:
- 确认私钥正确且未加密
- 尝试使用主私钥和子密钥解密
- GPG手动解密成功,但Node.js脚本无法复现
问题解答
1. 为什么Node.js报错而GPG手动解密成功?
GPG对密钥用途的校验更宽松——即使密钥未标记加密用途,仍会尝试用其解密;但openpgp库默认严格检查密钥的用途标记,若密钥没有encrypt权限,会直接判定为无效解密密钥,触发No decryption key packets found错误。
另外,CAST5算法支持差异:GPG默认内置CAST5支持,而openpgp库可能默认未启用该算法,或在密钥偏好未声明时拒绝处理。
2. 如何解决密钥标记及CAST5算法警告?
修复密钥用途标记
通过GPG给密钥添加加密权限:
- 导入私钥到GPG:
gpg --import private.key - 进入密钥编辑界面:
gpg --edit-key 7851C0CAFDBF2903 - 交互命令输入
addkey,选择RSA加密类型,设置有效期后输入save保存 - 导出修改后的私钥:
gpg --armor --export-secret-key 7851C0CAFDBF2903 > updated_private.key
之后用修改后的私钥在Node.js中重试解密。
处理CAST5算法问题
在代码中显式启用CAST5算法,可在解密前添加配置:
// 启用CAST5算法支持 openpgp.config.cipherAlgorithms.add(openpgp.enums.cipher.cast5);
或在解密选项中指定允许的算法:
const { data: decryptedData } = await openpgp.decrypt({ message, decryptionKeys: decryptedPrivateKey, format: 'utf8', config: { cipherAlgorithms: new Set([openpgp.enums.cipher.cast5, openpgp.enums.cipher.aes256]) } });
3. 代码是否遗漏子密钥或特定算法处理?
当前代码仅读取顶层私钥,若密钥包含子密钥,需确保子密钥被正确加载并具备解密权限。可修改代码如下:
// 读取私钥(确保加载所有子密钥) const privateKey = await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }); // 收集所有可用的解密密钥(主密钥+子密钥) const allDecryptionKeys = [decryptedPrivateKey]; if (decryptedPrivateKey.subkeys.length > 0) { allDecryptionKeys.push(...decryptedPrivateKey.subkeys.map(subkey => subkey.privateKey)); } // 解密时传入所有密钥 const { data: decryptedData } = await openpgp.decrypt({ message, decryptionKeys: allDecryptionKeys, format: 'utf8' });
同时建议升级openpgp库到最新版本,旧版本可能存在密钥解析或算法支持的bug:
npm update openpgp
内容的提问来源于stack exchange,提问作者CR00N0S
相关产品推荐
相关产品推荐

