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:
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 intoorg.bouncycastle.openpgp
Connect to the smart card in the USB dongle using
javax.smartcardio
APIs.Select the OpenPGP applet
val pgpAID = bytes(0xD2, 0x76, 0x00, 0x01, 0x24, 0x01) val answer = cardChannel.transmit(CommandAPDU(0x00, 0xA4, 0x04, 0x00, pgpAID))
Successfully present the right PIN to the card
val pin = "123456" return bytes(0x00, 0x20, 0x00, 0x82, pin.length) + pin.toByteArray(Charsets.UTF_8)
Send a quasi-successful (see below)
decipher
commandbytes(0x00, 0x2a, 0x80, 0x86, data.size) + data + bytes(0x00)
When
data = "xxxx".toByteArray()
, the result isSW=9000
(= success) but no data is returned. It's a naive test because the OpenPGP applet documentation on page 52 mentions thatthe command input (except padding indicator byte) shall be formatted according to PKCS#1 before encryption.
I have no idea how to encrypt the data and get it into PKCS#1 format.
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).
I created a GitHub repository with the entire code. It's written in Kotlin but should be easy to read.