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

标签 java encryption smartcard openpgp yubico

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

  1. 卡已初始化,使用 gpg 工具生成 key 。它通常有效。我有 .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 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/

相关文章:

java - 如何/无法将乱码/奇怪的文本转换为 utf-8 android (java)?

ios - 外部MD5ing算作 "encryption"吗?

java - 如何使用 Java 从 Windows (MSCAPI) 上的智能卡获取用户身份?

c# - 'hide' 密码短语、初始化向量等的最佳方法..用于类库中的加密

c++ - 如何在应用程序中将 com.apple.security.smartcard entitlement 设置为 yes

smartcard - GPG key 签名方 w。在 yubikey 上分离主 key 和子 key

java - 未找到 Gradle 方法 :'compile' 可能原因 : The Project

java - 如何更改另一个 java 类中的变量值?

java - NullPointerException,在scala中填充vaadin的IndexedContainer时

ios - 我想在 objective-c 中使用无填充的 CFB 加密创建 AES 128