我正在尝试在 Java 应用程序中实现基于 Yubikey NEO OpenPGP 智能卡小程序的 PGP 加密。这似乎是一门黑暗的艺术,用谷歌搜索这些东西并不容易,但这是我到目前为止的地方:
卡已初始化,使用 gpg 工具生成 key 。它通常有效。我有
.asc
格式的公钥,并设法将其加载到org.bouncycaSTLe.openpgp
使用
javax.smartcardio
API 连接到 USB 加密狗中的智能卡。选择 OpenPGP 小程序
val pgpAID = bytes(0xD2, 0x76, 0x00, 0x01, 0x24, 0x01) val answer = cardChannel.transmit(CommandAPDU(0x00, 0xA4, 0x04, 0x00, pgpAID))
成功向卡出示正确的 PIN
val pin = "123456" return bytes(0x00, 0x20, 0x00, 0x82, pin.length) + pin.toByteArray(Charsets.UTF_8)
发送准成功(见下文)
decipher
命令bytes(0x00, 0x2a, 0x80, 0x86, data.size) + data + bytes(0x00)
当
data = "xxxx".toByteArray()
时,结果为SW=9000
(=成功)但没有返回数据。这是一个天真的测试,因为第 52 页的 OpenPGP applet documentation 提到了这一点the command input (except padding indicator byte) shall be formatted according to PKCS#1 before encryption.
我不知道如何加密数据并将其转换为 PKCS#1 格式。
我也尝试通读 Yubico OpenPGP card implementation tests,但它只提供了另一个“失败”示例(第 196 行)。我尝试运行它,但结果不同:测试期望 SW=0050
(表示异常?)而我得到的是 SW=6f00
(没有精确的诊断,根据到 this document )。
我用整个代码创建了一个 GitHub repository。它是用 Kotlin 编写的,但应该易于阅读。
最佳答案
你的问题有点困惑,但我很确定你想使用与智能卡上的 RSA 私钥相对应的 RSA 公钥创建 PGP 加密消息,然后使用智能卡上的 RSA 私钥来(帮助)解密它们. PGP(就像几乎所有其他东西一样)使用混合加密,因此相关部分的 PGP 加密消息包括:
- 使用随机生成的工作 key 使用适当的对称算法(如 TDES 或 AES)加密的实际消息,称之为 K
- 工作 key K 加上一些由 RSA 使用收件人的公钥加密的元数据和由原始 PKCS#1 标准定义的填充,现在正式称为 RSAES-PKCS1-v1_5,但仍然被广泛称为 PKCS1,有点不准确。
您不需要执行加密步骤,因为任何实现该标准的软件都可以这样做,包括 GnuPG 或 BouncyCaSTLe 的 bcpg
库。如果您想自己做,也许对于使用伪造的 K 而没有真实消息的测试数据,您需要进行填充 和 RSA 模幂运算;在 Java 中,至少是 Oracle 或带有标准加密提供程序的 openjdk Java,您可以只使用通过 .getInstance("RSA/ECB/PKCS1Padding")
获得的 javax.crypto.Cipher
> 以通常的方式。
“PKCS1”加密填充(用于 RSA)如该文档第 52 页底部和第 53 页顶部所述,其内容与current OpenPGP spec相同,但格式不同(及更早版本),它引用并实际上等同于near-current PKCS#1 spec(及更早版本),所有这些都说它是:
- 一个字节00
- 一个字节02
- 足够多的非零随机字节使结果长度正确并且安全
- 一个字节00
- “明文”,对于 PGP 加密,实际上是按照the PGP spec指定格式的工作对称 key K。
注意段落开头
In case of the AES algorithm
似乎用于不同的选项,而不是 PGP AFAICS,在上一页中描述为
By option (announced in Extended capabilities) the card supports the decryption of a plain text with an AES-key stored in a special DO (D5). This is useful if no certificate or public key exists and the external world has a common secret with the card.
所以忽略它。
关于java - 用于 Yubico OpenPGP 智能卡的 PGP 数据加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33841380/