Files
yubikey/yubikey-piv-pcsc-apdu.md

4.7 KiB

Use OpenSC:

opensc-tool -c default  -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00
  -s 00:87:11:85:47:7c:45:82:00:85:41:
  04:65:2D:C5:8C:DC:1F:09:11:50:DB:91:F5:F5:8C:A5:32:A5:09:75:E2:34:20:79:09:10:C7:0F:E3:A3:AB:86:DC:
  EA:9C:70:9F:56:06:3B:CD:22:47:F7:D7:D5:7C:92:5C:8F:CF:F2:A2:A8:9A:E2:86:00:CA:9A:C1:5E:2A:10:D2

Using reader with a card: Yubico YubiKey OTP+FIDO+CCID
Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 
Received (SW1=0x90, SW2=0x00):
61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 a.O.......y.O...
00 03 08                                        ...
Sending: 00 87 11 85 47 7C 45 82 00 85 41 04 65 2D C5 8C DC 1F 09 11 50 DB 91 F5 F5 8C A5 32 A5 09 75 E2 34 20 79 09 10 C7 0F E3 A3 AB 86 DC EA 9C 70 9F 56 06 3B CD 22 47 F7 D7 D5 7C 92 5C 8F CF F2 A2 A8 9A E2 86 00 CA 9A C1 5E 2A 10 D2 
Received (SW1=0x90, SW2=0x00):
7C 22 82 20 7B A1 97 EA 65 CD 88 32 8F 2A 86 25 |". {...e..2.*.%
B5 B7 80 22 BD 89 47 93 7E D1 FC EF 88 9C D3 6C ..."..G.~......l
7A C3 C0 F7                                     z...

Use card-cli:

card-cli piv-ecdh -s 85 --epk 04652DC58CDC1F091150DB91F5F58CA532A50975E23420790910C70FE3A3AB86DCEA9C709F56063BCD2247F7D7D57C925C8FCFF2A2A89AE28600CA9AC15E2A10D2 --private --json
{
  "pk_point_hex": "04645990f3e6f93abda9221bd91919f3bba59eab5aa17b31abd24a2226066d3ceb26178dd741e327d385ba89edc14e1ea8f464658da05c80ab4d785ee3757b7adb",
  "shared_secret_hex": "7ba197ea65cd88328f2a8625b5b78022bd8947937ed1fcef889cd36c7ac3c0f7"
}

Use java:

import javax.smartcardio.*;
import java.io.ByteArrayOutputStream;
import java.util.List;

public class YubikeyPivTest {

    public static void main(String[] args) throws CardException {
        final TerminalFactory factory = TerminalFactory.getDefault();
        final List<CardTerminal> terminals = factory.terminals().list();
        System.out.println("Smart card terminals: " + terminals);

        CardTerminal terminal = terminals.get(0);

        System.out.println("First terminal: " + terminal);

        final Card card = terminal.connect("*");
        System.out.println("\n\nCard inserted: " + card);
        final CardChannel channel = card.getBasicChannel();

        final ATR atr = card.getATR();
        System.out.println("ATR della carta: " + bytes2String(atr.getBytes()));

        final byte[] selectCommand = string2Bytes("00:a4:04:00:09:a0:00:00:03:08:00:00:10:00".replace(":", ""));
        final CommandAPDU selectApdu = new CommandAPDU(selectCommand);
        final ResponseAPDU selectResponse = channel.transmit(selectApdu);
        System.out.println("SELECT: " + bytes2String(selectResponse.getBytes()));

        final byte[] ecdhCommand = string2Bytes(("00:87:11:85:47:7c:45:82:00:85:41:" +
                "04:65:2D:C5:8C:DC:1F:09:11:50:DB:91:F5:F5:8C:A5:32:A5:09:75:E2:34:20:79:09:10:C7:0F:E3:A3:AB:86:DC:" +
                "EA:9C:70:9F:56:06:3B:CD:22:47:F7:D7:D5:7C:92:5C:8F:CF:F2:A2:A8:9A:E2:86:00:CA:9A:C1:5E:2A:10:D2").replace(":", ""));
        final CommandAPDU ecdhApdu = new CommandAPDU(ecdhCommand);
        final ResponseAPDU ecdhResponse = card.getBasicChannel().transmit(ecdhApdu);
        System.out.println("ECDH: " + bytes2String(ecdhResponse.getBytes()));

        card.disconnect(false);
    }

    private static String bytes2String(byte[] bytes) {
        StringBuilder string = new StringBuilder();
        for (byte b : bytes) {
            String hexString = Integer.toHexString(0x00FF & b);
            string.append(hexString.length() == 1 ? "0" + hexString : hexString);
        }
        return string.toString();
    }

    private static byte[] string2Bytes(String str) {
        int len = str.length();
        if ((len % 2) != 0) {
            throw new RuntimeException("String format error: " + str);
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (int i = 0; i < len; i++) {
            String substr = new String(new char[]{str.charAt(i++), str.charAt(i)});
            baos.write((byte) Integer.parseInt(substr, 16));
        }
        return baos.toByteArray();
    }
}
java YubikeyPivTest
Smart card terminals: [PC/SC terminal Yubico YubiKey OTP+FIDO+CCID]
First terminal: PC/SC terminal Yubico YubiKey OTP+FIDO+CCID


Card inserted: PC/SC card in Yubico YubiKey OTP+FIDO+CCID, protocol T=1, state OK
ATR della carta: 3bfd1300008131fe158073c021c057597562694b657940
SELECT: 61114f0600001000010079074f05a0000003089000
ECDH: 7c2282207ba197ea65cd88328f2a8625b5b78022bd8947937ed1fcef889cd36c7ac3c0f79000

Reference:

  1. https://stackoverflow.com/questions/23422379/javax-smartcardio-read-all-smart-card
  2. https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/auth-key-agree.html
  3. https://github.com/jnasmartcardio/jnasmartcardio