用于Yubico OpenPGP智能卡的PGP数据加密

我试图在Java应用程序中基于Yubikey NEO OpenPGP智能卡小程序实现PGP加密。 这似乎是一个黑暗的艺术,并不容易谷歌这个东西,但这里是我到目前为止:

  1. 卡被初始化,密钥是使用gpg工具生成的。 它一般工作。 我有我的公钥以.asc格式,并设法加载到org.bouncycastle.openpgp

  2. 使用javax.smartcardio API连接到USB加密狗的智能卡。

  3. 选择OpenPGP小程序

     val pgpAID = bytes(0xD2, 0x76, 0x00, 0x01, 0x24, 0x01) val answer = cardChannel.transmit(CommandAPDU(0x00, 0xA4, 0x04, 0x00, pgpAID)) 
  4. 成功向卡提交正确的PIN码

     val pin = "123456" return bytes(0x00, 0x20, 0x00, 0x82, pin.length) + pin.toByteArray(Charsets.UTF_8) 
  5. 发送准成功(见下文) 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密钥来解密纯文本。 如果没有证书或公钥存在,并且外部世界与卡有共同的秘密,这是有用的。

所以无视它。