用于Yubico OpenPGP智能卡的PGP数据加密
我试图在Java应用程序中基于Yubikey NEO OpenPGP智能卡小程序实现PGP加密。 这似乎是一个黑暗的艺术,并不容易谷歌这个东西,但这里是我到目前为止:
-
卡被初始化,密钥是使用gpg工具生成的。 它一般工作。 我有我的公钥以
.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小程序文档提到了这一点在加密之前,命令输入(填充指示符字节除外)应根据PKCS#1格式化。
我不知道如何加密数据并将其转换为PKCS#1格式。
我也尝试通过Yubico OpenPGP卡实现测试阅读,但它只提供了另一个“失败”的例子(196行)。 我尝试运行,但结果是不同的:测试期望SW=0050
(指示例外?),我得到的是SW=6f00
(根据本文档没有精确的诊断)。
我用整个代码创建了一个GitHub仓库 。 这是写在Kotlin,但应该很容易阅读。
你的问题有点困惑,但是我敢肯定你想用你的智能卡上的RSA私钥对应的RSA公钥创建PGP加密消息,然后使用智能卡上的RSA私钥来(帮助)解密它们。 PGP(就像其他的一切)使用混合加密,所以相关部分的PGP加密消息包括:
- 使用随机生成的工作密钥,用适当的对称算法(如TDES或AES)加密的实际消息称为K
- 工作密钥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的顶部所述,内容尽管不是格式,但是与当前的OpenPGP规范 (及更早版本)相同,有效地与近乎PKCS#1规范 (及更早版本)相同,所有这些都说明:
- 一个字节00
- 一个字节02
- 足够的字节非零随机,使结果正确的长度和安全
- 一个字节00
- 用于PGP加密的“明文”实际上是按照PGP规范中规定格式化的工作对称密钥K.
注意开始的段落
在AES算法的情况下
似乎是一个不同的选择,而不是PGP AFAICS,在前面的页面描述为
通过选项(在扩展function中宣布),该卡支持使用存储在特殊DO(D5)中的AES密钥来解密纯文本。 如果没有证书或公钥存在,并且外部世界与卡有共同的秘密,这是有用的。
所以无视它。