Add 'yubikey-piv-pcsc-apdu'
This commit is contained in:
110
yubikey-piv-pcsc-apdu
Normal file
110
yubikey-piv-pcsc-apdu
Normal 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
|
||||
Reference in New Issue
Block a user