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

ato*_*tok 12 java encryption smartcard openpgp yubico

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

  1. 卡被初始化,密钥使用gpg工具生成.它通常有效.我有.asc格式的公钥,并设法加载它org.bouncycastle.openpgp

  2. 使用javax.smartcardioAPI 连接USB加密狗中的智能卡.

  3. 选择OpenPGP小程序

    val pgpAID = bytes(0xD2, 0x76, 0x00, 0x01, 0x24, 0x01)
    val answer = cardChannel.transmit(CommandAPDU(0x00, 0xA4, 0x04, 0x00, pgpAID))
    
    Run Code Online (Sandbox Code Playgroud)
  4. 成功向卡片出示正确的PIN码

    val pin = "123456"
    return bytes(0x00, 0x20, 0x00, 0x82, pin.length) + pin.toByteArray(Charsets.UTF_8)
    
    Run Code Online (Sandbox Code Playgroud)
  5. 发送准成功(见下文)decipher命令

    bytes(0x00, 0x2a, 0x80, 0x86, data.size) + data + bytes(0x00)
    
    Run Code Online (Sandbox Code Playgroud)

    何时data = "xxxx".toByteArray(),结果是SW=9000(=成功)但没有返回数据.这是一个天真的测试,因为第52页的OpenPGP applet文档提到了这一点

    在加密之前,命令输入(填充指示符字节除外)应根据PKCS#1格式化.

我不知道如何加密数据并将其转换为PKCS#1格式.

我也试过阅读Yubico OpenPGP卡实现测试,但它只提供了另一个"失败"的例子(第196行).我尝试运行它,但结果是不同的:测试期望SW=0050(表示异常?)和我得到的是SW=6f00(没有精确的诊断,根据这个文件).

我用完整的代码创建了一个GitHub存储库.它是用Kotlin编写的,但应该很容易阅读.

dav*_*085 6

您的问题有点混淆,但我很确定您要使用与智能卡上的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中,你可以只使用一个javax.crypto.Cipher与获得.getInstance("RSA/ECB/PKCS1Padding")通常的方式.

"PKCS1"加密填充(用于RSA)如该文档的第52页底部和页面53的顶部所述,其内容相同但不是当前OpenPGP规范(及更早版本)的格式,其指的是和实际上与近电流PKCS#1规范(及更早版本)相同,所有这些都说:

  • 一个字节00
  • 一个字节02
  • 足够的字节非零随机,使结果的长度正确,安全
  • 一个字节00
  • 在"明文",这对PGP加密实际上是在规定的格式化工作对称密钥K 的PGP规范.

注意段落的开头

在AES算法的情况下

似乎是针对不同的选项,而不是PGP AFAICS,在上一页中描述为

通过选项(在扩展功能中公布),该卡支持使用存储在特殊DO(D5)中的AES密钥解密纯文本.如果不存在证书或公钥,并且外部世界与卡有共同的秘密,这将非常有用.

所以忽略它.