Add 'yubikey-piv-pcsc-apdu'

This commit is contained in:
2024-06-26 23:36:20 +08:00
parent fb607a1eba
commit 3111993787

110
yubikey-piv-pcsc-apdu Normal file
View File

@@ -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<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();
}
}
```
```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
```
<br>
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