>卡被初始化,使用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,pgpAID))
>成功地将正确的PIN提供给卡
val pin = "123456" return bytes(0x00,0x20,0x82,pin.length) + pin.toByteArray(Charsets.UTF_8)
>发送准成功(见下文)解密命令
bytes(0x00,0x2a,0x80,0x86,data.size) + data + bytes(0x00)
当data =“xxxx”.toByteArray()时,结果为SW = 9000(= success),但不返回任何数据.这是一个天真的测试,因为第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与整个代码.它写在科特林,但应该很容易阅读.
解决方法
>使用适当的对称算法(如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页的顶部所述,尽管不是格式与current OpenPGP spec(及更早版本)相同,但是引用和有效地相同到near-current PKCS#1 spec(和更早),所有这些都说是:
>一个字节00
>一个字节02
>足够的字节非零随机,使结果正确的长度和安全
>一个字节00
>“明文”,PGP加密实际上是the PGP spec规定的工作对称密钥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.
所以忽略它.