You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS使用验证密钥时openpgp.decrypt解密失败求助

OpenPGP解密Azure Function排查建议

问题描述

我有一个运行Node.js OpenPGP解密模块的Azure Function,解密自身生成的加密文件正常,但解密第三方用我的公钥加密的文件时,能成功获取对方密钥却解密失败,且无明确错误提示。

日志输出的message结构

message Bh {
  packets: Ku(2) [
    ju {
      version: 3,
      publicKeyID: [Ke],
      publicKeyAlgorithm: 1,
      sessionKey: null,
      sessionKeyAlgorithm: null,
      encrypted: [Object],
      packets: Ku(0) [],
      fromStream: false
    },
    Ou {
      version: 1,
      encrypted: [v],
      packets: Ku(0) [],
      fromStream: 'array'
    },
    stream: v(2) [
      [ju],
      [Ou],
      [Symbol(doneWritingResolve)]: [Function (anonymous)],
      [Symbol(doneWritingReject)]: [Function (anonymous)],
      [Symbol(doneWritingPromise)]: [Promise],
      [Symbol(readingIndex)]: 2
    ]
  ],
  fromStream: false
}

解密错误栈跟踪

Decryption error
    at /home/site/wwwroot/node_modules/openpgp/dist/node/openpgp.min.js:2:178460
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async ju.decrypt (/home/site/wwwroot/node_modules/openpgp/dist/node/openpgp.min.js:2:291018)
    at async /home/site/wwwroot/node_modules/openpgp/dist/node/openpgp.min.js:2:345501
    at async Promise.all (index 0)
    at async /home/site/wwwroot/node_modules/openpgp/dist/node/openpgp.min.js:2:344837
    at async Promise.all (index 0)
    at async /home/site/wwwroot/node_modules/openpgp/dist/node/openpgp.min.js:2:344447
    at async Promise.all (index 0)
    at async Bh.decryptSessionKeys (/home/site/wwwroot/node_modules/openpgp/dist/node/openpgp.min.js:2:344404)

函数代码

const openpgp = require('openpgp');
const { getPrivateKey, readMessage, isBinary, getDecryptFileName, getVerificationKey } = require('./utils');
const { BlobServiceClient } = require("@azure/storage-blob");
const { Buffer } = require('node:buffer');
const handler = async function (context, decryptThis) {
    context.log("JavaScript blob trigger function processed blob \nBlob:", context.bindingData.blobTrigger, "\nBlob Size:", decryptThis.length, "Bytes");
    const blobName = context.bindingData.blobTrigger;
    try {
        context.log('getPrivateKey');
        const decryptedKey = await getPrivateKey(blobName);
        context.log('getVerficationKey');
        const verificationKey = await getVerificationKey(blobName, context.log);
        context.log('isBinary');
        const fileIsBinary = isBinary(blobName);
        context.log('readMessage');
        const message = await readMessage(decryptThis, fileIsBinary, context.log);
        context.log('message', message);
        const decryptOpts = {
            message,
            decryptionKeys: decryptedKey,
            format: fileIsBinary ? 'binary' : 'utf8',
        };
        if (verificationKey) {
            context.log('has verificationKey');
            decryptOpts.verificationKeys = verificationKey;
            decryptOpts.expectSigned = false; // Don't fail if signature fails verification.
        }
        context.log('decrypting...');
        const decrypted = await openpgp.decrypt(decryptOpts);
        context.log('decrypted', decrypted);
        const data = decrypted.data;
        context.log('isBuffer', Buffer.isBuffer(data));
        context.log(data ? 'has data ' + typeof data : 'no data');
        const buf = Buffer.from(data);
        const saveName = getDecryptFileName(blobName);
        context.log(`desired filename ${saveName}`);
        const blobServiceClient = BlobServiceClient.fromConnectionString(
            process.env.FILESECURE_CONNECTION_STRING,
        );
        const container = blobServiceClient.getContainerClient('decrypted');
        const blob = container.getBlockBlobClient(saveName);
        const result = await blob.uploadData(buf);
        context.log(result);
    } catch (err) {
        context.log(`DECRYPT ERROR: ${err.message}`);
    }
};

module.exports = handler;

排查建议

  • 核对密钥匹配:确认第三方使用的公钥与你用于解密的私钥严格配对,通过message中的publicKeyID字段核对两者的Key ID是否一致。
  • 开启详细日志:在代码开头添加openpgp.config.logger = console;,或者将Azure Function的日志级别设为Debug,获取解密过程的详细日志,重点关注sessionKey解密阶段的细节。
  • 检查文件格式处理:确认第三方生成的PGP文件是ASCII-armored还是二进制格式,验证readMessage工具函数是否能正确解析这两种格式。
  • 确认私钥状态:添加日志输出decryptedKey.isDecrypted(),确保获取到的私钥是完全解密(无密码保护或已正确解锁)的状态。
  • 排除签名干扰:暂时移除verificationKeys和expectSigned配置,仅执行纯解密操作,排查是否是签名验证环节的隐性错误导致解密失败。
  • 检查版本兼容性:确认你的openpgp库版本与第三方加密工具版本是否兼容,从message中可以看到对方使用的是v3版本密钥,需确认当前库对v3密钥的支持是否有特殊要求。
  • 本地测试验证:将第三方加密文件下载到本地,使用相同的私钥和openpgp库版本进行本地解密测试,排除Azure Function环境(如内存限制、编码处理差异)的影响。

内容的提问来源于stack exchange,提问作者Harvey A. Ramer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 10:32:04