From 31119937879983f9fea6398a5ad50546cc123d4d Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Wed, 26 Jun 2024 23:36:20 +0800 Subject: [PATCH] Add 'yubikey-piv-pcsc-apdu' --- yubikey-piv-pcsc-apdu | 110 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 yubikey-piv-pcsc-apdu diff --git a/yubikey-piv-pcsc-apdu b/yubikey-piv-pcsc-apdu new file mode 100644 index 0000000..6a70228 --- /dev/null +++ b/yubikey-piv-pcsc-apdu @@ -0,0 +1,110 @@ +Use `OpenSC`: +```shell +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`: +```shell +card-cli piv-ecdh -s 85 --epk 04652DC58CDC1F091150DB91F5F58CA532A50975E23420790910C70FE3A3AB86DCEA9C709F56063BCD2247F7D7D57C925C8FCFF2A2A89AE28600CA9AC15E2A10D2 --private --json +{ + "pk_point_hex": "04645990f3e6f93abda9221bd91919f3bba59eab5aa17b31abd24a2226066d3ceb26178dd741e327d385ba89edc14e1ea8f464658da05c80ab4d785ee3757b7adb", + "shared_secret_hex": "7ba197ea65cd88328f2a8625b5b78022bd8947937ed1fcef889cd36c7ac3c0f7" +} +``` + +Use `java`: + +```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 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(); + } +} +``` + +```shell +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 \ No newline at end of file