【发布时间】:2018-03-16 07:46:16
【问题描述】:
我有一个 PGP Public-Key Encrypted Session Packet,我想从中提取会话密钥,以便我可以单独解密会话密钥。我正在使用 BouncyCastle 库并像这样提取会话密钥:
private static void outputSessionKey(String path) throws FileNotFoundException, IOException {
BCPGInputStream input = new BCPGInputStream(PGPUtil.getDecoderStream(new FileInputStream(path)));
Packet packet;
while((packet = input.readPacket()) != null) {
if (packet instanceof PublicKeyEncSessionPacket) {
PublicKeyEncSessionPacket encPacket = (PublicKeyEncSessionPacket) packet;
byte[] encKey = encPacket.getEncSessionKey()[0];
FileOutputStream output = new FileOutputStream("session_key_enc.bin");
output.write(encKey);
output.close();
}
}
input.close();
}
我希望能够使用 openssl 解密会话密钥:
openssl rsautl -decrypt -in session_key_enc.bin -out session_key_decoded.bin -inkey private.pem
其中 session_key_enc.bin 是我的二进制格式的加密会话密钥,private.pem 是我用来加密 GPG 中数据的公钥的对应私钥.在加密数据之前,我将 RSA 密钥对的公钥部分转换为 PGP 格式的密钥并将其导入 GPG。
当我运行 OpenSSL 命令时,我收到此错误:
RSA operation error
140624851898072:error:0406506C:rsa routines:RSA_EAY_PRIVATE_DECRYPT:data greater than mod len:rsa_eay.c:518:
在检查 session_key_enc.bin 后,我发现该文件是 258 字节。考虑到我使用的是 2048 位 RSA 密钥并且规范表明加密的会话密钥是由 n 修改的,这似乎是不可能的:
RSA 加密的算法特定字段 - RSA 加密值 m**e mod n 的多精度整数 (MPI)。
上述公式中的“m”值是从会话密钥导出的 如下。首先,会话密钥以一个八位字节为前缀 指定对称加密的算法标识符 用于加密以下对称加密数据的算法 包。然后附加一个两个八位字节的校验和,它等于 前一个会话密钥八位字节的总和,不包括算法 标识符,以 65536 为模。然后按照中所述对这个值进行编码 [RFC3447] 第 7.2.1 节中的 PKCS#1 块编码 EME-PKCS1-v1_5 到 形成上述公式中使用的“m”值。请参阅第 13.1 节 本文档是关于 OpenPGP 使用 PKCS#1 的说明。
任何关于如何解决这个难题的建议将不胜感激,谢谢!
【问题讨论】:
-
您是否拆分了数据包的前几个标头字节(或确保 Bouncy Castle 已经这样做了)?
pgpdump -pi还应该将会话密钥打印为整数值,您应该能够将 Java 代码的结果与这个进行比较。 -
@JensErat 事实证明,Bouncy Castle 以 MPI 格式输出会话密钥,前两个字节代表总边。剥离这些后,我能够解密会话密钥,但仍然无法从解码的原始字节中获取任何明智的密钥
标签: openssl cryptography bouncycastle gnupg openpgp