使用OpenPGP.js解密非装甲的PGP文件

9

我正在开发一个基于Node的应用程序,其中我已经构建了一个解密函数,并使用Openpgp.js npm模块使其工作。我接收各种使用我们公钥创建的PGP客户端文件,使用我们的私钥进行解密,然后将解密后的版本放置在一个文件夹中供我访问,只要这些文件是加强过的,一切都很顺利。以下是一些代码示例,显示事件的顺序:

const encryptedData = fs.readFileSync(encryptedFilePath, 'utf8')
openpgp.decrypt({
        message: openpgp.message.readArmored(encryptedData),
        publicKeys,
        privateKey
}).then( (decrypted) => { fs.writeFile(decryptedFilePath, decrypted.data } )

当一个加密文件传输过来时,一切正常,我会在指定的文件夹中得到已解密的文件。当在文本编辑器中打开这些文件时,格式如下:
-----BEGIN PGP MESSAGE-----
WBh2X7KwfEBDx0LEE1FzlnvxZs44o62FclpTazJpcl9J7DjwVfg9cHCID0TAN6Y6
B3b5bCQQFe1wTgpIkVtd0mFGQx7KGHj4FGte53qseVxC2bfq9PGKRIAUg6olr+82

然而,我们的客户使用关闭了装甲选项加密文件,因此在文本编辑器中打开这些文件时,它们以十六进制类型格式呈现...

7403 436d e6c0 f941 daac 945b 9a81 f066
6cd2 0032 5df0 9ca2 23a0 6eec a7bb f24c
a941 99a8 1053 ae23 f88b 245c f709 c2b2

或者编码为文本文件,看起来像这样:
DµÉ‰í+�3K€Ð�˜PªeZ_|Ò®ó0��ãZqRµ3!ŒpuÉW�NZrìÚk´
Aˆ›œiêø8�Ú�ól:äΟ”�6‡)
w�¬ÌŒWÝÚ¢�Q��œ�œ?�H¨¿�œ//�ÃBA�´>(%°�e�

这最后两个问题与我在代码示例中使用console log输出"encryptedData"时看到的内容相似。

当任何非加装文件过来时,进程都会失败,并且一开始出现了几种不同类型的错误,具体如上所示。我去掉了fs.readFileSync中的'utf8'编码,并将"readArmored"替换为"fromBinary"以处理二进制数据,但是之后我会收到有关"Invalid session key for decryption"的错误消息。因此,我尝试在主要解密之前使用"decryptSessionKey"函数,因为它在文档中显示,但这会给我带来一个未定义的密钥和一个关于"没有找到对称加密会话密钥包"的错误。此外,我可能朝错误的方向努力,因为使用Openpgp.js的二进制需要密码,而我认为这与解锁我的私钥的密码(即我唯一拥有的密码)不同。

我已经搜索了整个Openpgp.js文档并像疯子一样Google,但似乎找不到一个可靠的程序来修改我的代码,使其适用于解密未加装的文件。(然而,每个传入的文件在使用桌面解密程序(如PGP Desktop)解密时都能快速且无误地解密,因此我无法弄清楚我的差异在哪里以及为什么解决方案不明显。)有没有人对此有任何经验或可能的解决方案?


对于一个非常相似的问题,这个答案建议使用openpgp.message.fromBinary()而不是openpgp.message.readArmored()。我在JavaScript方面没有更深的专业知识,但我认为在调用openpgp.decrypt()函数之前可以执行以下操作:try { message = openpgp.message.readArmored(encryptedData); } catch(err) { message = openpgp.message.fromBinary(encryptedData); } - 0range
谢谢您的回复,虽然我看到了您提供的那篇文章,但它似乎并没有帮助我。当我使用“fromBinary”时,我会得到一个“数据必须是Uint8array格式”的错误,因为我正在使用utf-8字符串传递它。如果我使用openpgp实用程序将字符串转换为Uint8,然后传递数据,我会得到另一个错误:“解密消息时出错:无效的会话密钥。”这些都是我可以直接放入PGP桌面应用程序中并立即解密的文件。我一定是漏掉了什么技巧... - threepears
从Keys中删除所有不必要的空格。 - Gaurav Patil
1个回答

2

openpgp.message.readArmored() 的非装甲版本是 openpgp.message.read()

因此,像这样的内容应该可以工作:

const encryptedData = fs.readFileSync(encryptedFilePath, 'utf8')

if encryptedData.startsWith('-----BEGIN PGP MESSAGE-----')
    encryptedMessage = openpgp.message.readArmored(encryptedData)
else
    var TextEncoder = require('text-encoding').TextEncoder;
    var encryptedUint8 = new TextEncoder().encode(encryptedData);
    encryptedMessage = openpgp.message.read(encryptedUint8)

openpgp.decrypt({
    message: encryptedMessage,
    publicKeys,
    privateKey
}).then( (decrypted) => { fs.writeFile(decryptedFilePath, decrypted.data } )

(如果您在代码中提前加载了TextEncoder,则此处不需要var TextEncoder行)



谢谢您的回复!我尝试了这个方法,但是像我担心的那样,它对于加密文件可以正常工作,但其他文件仍然无法通过。每一个没有加密的文件都会出现错误,错误信息是“TypeError: input.subarray is not a function.” 如果需要,我可以提供堆栈跟踪信息,但最后一项是“at Object.read (/Users/......./openpgp/dist/openpgp.js:16777:61)”。如果您有任何进一步的建议来解决这个错误,我很乐意听取,因为我已经花了很多时间尝试解决这个问题,但仍然是个谜..... - threepears
@threepears - 很抱歉,在我浏览文档时,并没有注意到read()方法需要一个类型为Uint8array的参数。我会添加一个转换步骤... - Stobor
@Stobor - 我该如何使用流来实现完全相同的事情,而不是将文件读入内存? 我将要做完全相同的事情,但我的文件相当大,所以我不想将它们读入内存。我已经使用加密的文件流使其正常运作,但是非加密的文件在调用 'await openpgp.message.read(readStream, true)' 时会卡住。另外,我尝试解密的非加密文件似乎是以“编码文本格式”表示的,类似于 OP 中的第二个非加密样例。 - André Engelbrecht

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接