用于Yubico OpenPGP智能卡的PGP数据加密 [英] PGP data encryption for use with Yubico OpenPGP Smart Card

查看:365
本文介绍了用于Yubico OpenPGP智能卡的PGP数据加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement PGP encryption based on Yubikey NEO OpenPGP Smart Card applet in a Java application. It seems to be a dark art and is not easy to google this stuff but here is where I got so far:


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

  1. The card is initialized, keys are generated using gpg tool. It generally works. I have my public key in .asc format and managed to load it into org.bouncycastle.openpgp

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

Connect to the smart card in the USB dongle using javax.smartcardio APIs.

选择OpenPGP小程序

Select the OpenPGP applet

val pgpAID = bytes(0xD2, 0x76, 0x00, 0x01, 0x24, 0x01)
val answer = cardChannel.transmit(CommandAPDU(0x00, 0xA4, 0x04, 0x00, pgpAID))


  • 成功地向卡提供正确的PIN

  • Successfully present the right PIN to the card

    val pin = "123456"
    return bytes(0x00, 0x20, 0x00, 0x82, pin.length) + pin.toByteArray(Charsets.UTF_8)
    


  • 发送准成功(见下文)解密命令

    bytes(0x00, 0x2a, 0x80, 0x86, data.size) + data + bytes(0x00)
    

    data =xxxx.toByteArray()时,结果为 SW = 9000 (=成功),但不返回任何数据。这是一个天真的测试,因为 OpenPGP小程序文档(第52页)提到

    When data = "xxxx".toByteArray(), the result is SW=9000 (= success) but no data is returned. It's a naive test because the OpenPGP applet documentation on page 52 mentions that


    命令输入(填充指示符字节除外)应为加密前根据PKCS#1格式的

    the command input (except padding indicator byte) shall be formatted according to PKCS#1 before encryption.


  • 我不知道如何加密数据并将其转换为PKCS#1格式。 / strong>

    I have no idea how to encrypt the data and get it into PKCS#1 format.

    我也尝试阅读 Yubico OpenPGP卡实现测试,但它只提供另一个失败示例(第196行)。我尝试运行,但结果是不同的:测试期望 SW = 0050 (表示异常?),我得到的是 SW = 6f00 (根据此文档,无准确诊断)。

    I also tried reading through Yubico OpenPGP card implementation tests but it only provides another "failing" example (line 196). I tried running that but the result is different: the test expects SW=0050 (indicating an exception?) and what I get is SW=6f00 (No precise diagnosis, according to this document).

    我创建了一个 GitHub存储库,整个代码。它是写在科特林,但应该很容易阅读。

    I created a GitHub repository with the entire code. It's written in Kotlin but should be easy to read.

    推荐答案

    你的问题有点困惑,但我很确定你想使用与智能卡上的RSA私钥相对应的RSA publickey创建PGP加密消息,然后使用智能卡上的RSA私钥(帮助)对其进行解密。 PGP(像其他一切一样)使用混合加密,所以相关部分中的PGP加密消息包括:

    Your question is somewhat confused, but I'm pretty sure you want to create PGP encrypted messages using an RSA publickey corresponding to the RSA privatekey on your smartcard, and then use the RSA privatekey on the smartcard to (help) decrypt them. PGP (like practically everything else) uses hybrid encryption, so a PGP encrypted message in relevant part consists of:


    • 使用随机生成的工作密钥的TDES或AES等适当的对称算法,将工作密钥K加上一些由RSA加密的元数据,使用收件人的publickey和由原始数据定义的填充PKCS#1标准,现在正式称为RSAES-PKCS1-v1_5,但仍然被广泛地称为PKCS1。

    你不应该需要执行加密步骤,因为执行标准的任何软件都可以这样做,包括GnuPG或BouncyCastle的 bcpg 库。如果您想自己做,或许使用假K并且没有真实消息的测试数据,则需要进行填充和/或RSA模幂运算;在Java中,至少有Oracle或openjdk Java与标准加密提供程序,您可以使用 javax.crypto.Cipher 获得 .getInstance(RSA / ECC / PKCS1Padding)

    You shouldn't need to do the encryption steps because any software that implements the standard can do so, including GnuPG or BouncyCastle's bcpg library. If you want to do it yourself, perhaps for test data using a faked K and no real message, you need to do the padding and RSA modular exponentiation; in Java, at least Oracle or openjdk Java with standard crypto providers, you can just use a javax.crypto.Cipher obtained with .getInstance("RSA/ECB/PKCS1Padding") in the usual way.

    PKCS1加密填充(用于RSA)如第52页的底部和该文件的第53页的顶部所述,其内容相同但不是格式与当前的OpenPGP规范(及更早版本),它引用并且实际上与近期PKCS#1 spec (及更早版本),所有这些都表示:

    "PKCS1" encryption padding (for RSA) is as described at the bottom of page 52 and top of page 53 of that document, which is identical in content though not format to the current OpenPGP spec (and earlier), which refers to and is effectively identical to near-current PKCS#1 spec (and earlier), all of which say it is:


    • 一个字节00

    • 一个字节02

    • 足够的字节非零随机使结果正确的长度和安全

    • 一个字节00

    • 明文,用于PGP加密实际上是工作对称密钥K格式如 PGP规格所规定。

    • one byte 00
    • one byte 02
    • enough bytes nonzero random to make the result the correct length and be secure
    • one byte 00
    • the "plaintext", which for PGP encryption is actually the working symmetric key K formatted as specified in the PGP spec.

    注意开始


    AES算法的情况

    In case of the AES algorithm

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

    appears to be for a different option, not PGP AFAICS, described on the previous page as


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

    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.

    so忽略它。

    这篇关于用于Yubico OpenPGP智能卡的PGP数据加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆