Skip to content

Instantly share code, notes, and snippets.

@tsenger
Created March 9, 2016 13:30
Show Gist options
  • Save tsenger/ceb8d05febc684815609 to your computer and use it in GitHub Desktop.
Save tsenger/ceb8d05febc684815609 to your computer and use it in GitHub Desktop.
Test for PACE per PCSC reader with pinpad
package de.tsenger.sandbox;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.smartcardio.Card;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;
import de.tsenger.animamea.tools.HexString;
public class PACEPinpadTester {
/**
* @param args
* @throws CardException
* @throws IOException
*/
public static void main(String[] args) throws CardException, IOException {
// TerminalFactory factory = TerminalFactory.getDefault();
// List<CardTerminal> terminals = factory.terminals().list();
// System.out.println("Terminals: " + terminals);
CardTerminal terminal = TerminalFactory.getDefault().terminals().list()
.get(2);
Card card = terminal.connect("T=1");
byte[] chat = HexString.hexToBuffer("7F 4C 12 06 09 04 00 7F 00 07 03 01 02 02 53 05 3f ff ff ff f7");
byte chatLen = (byte) chat.length;
// byte[] certDescription = HexString.hexToBuffer("308202D5060A04007F00070301030101A10E0C0C442D547275737420476D6248A2181316687474703A2F2F7777772E642D74727573742E6E6574A3120C1053594E4348524F4E49545920476D6248A429132768747470733A2F2F7777772E73796E6368726F6E6974792E6E65742F64656D6F706F7274616C2FA58201F20C8201EE4E616D652C20416E7363687269667420756E6420452D4D61696C2D4164726573736520646573204469656E7374616E626965746572733A0D0A53594E4348524F4E49545920476D62480D0A57696E7A65726C616572205374722E20320D0A3037373435204A656E610D0A6E70614073796E6368726F6E6974792E64650D0A0D0A5A7765636B2064657220446174656EEFBFBD6265726D6974746C756E673A0D0A4964656E746966697A696572756E6720756E642052656769737472696572756E67207A756D2070657273EFBFBD6E6C696368656E204B756E64656E6B6F6E746F0D0A0D0A5A757374EFBFBD6E6469676520446174656E73636875747A626568EFBFBD7264653A0D0A5468EFBFBD72696E676572204C616E64657376657277616C74756E6773616D74205265666572617420486F6865697473616E67656C6567656E68656974656E2C20476566616872656E6162776568720D0A5765696D6172706C61747A20340D0A3939343233205765696D61720D0A54656C3A20283033203631292033372037332037322035380D0A4661783A20283033203631292033372037332037332034360D0A706F73747374656C6C6540746C7677612E7468756572696E67656E2E64650D0A416E737072656368706172746E65723A204672617520416E6B65204E65756D616E6E0D0AA7683166042012054BDCDD69F93AFDBC8666B908C386B009821730C96C3C066F8E6A20D0BE0D0420D97D56EB57F16D0510FD77DE1B964D186E69CED9E6E17FBEA7DBB0F5B3A814650420E9B2B7E1430EFDE9E99A25603AD32E2671EFB6B00D921439428DF982CE168D44");
// byte[] certDescription = HexString.hexToBuffer("3081B0060A04007F00070301030101A1"
// +"160C146D744720426572656368746967"
// +"756E67732D4341A3210C1F6D74472065"
// +"49442D5365727665722044656D6F2041"
// +"70706C69636174696F6EA41413126874"
// +"7470733A2F2F6569642E6D74672E6465"
// +"A52B0C29546573742064657220416E77"
// +"656E64756E67206D69742064656D206D"
// +"74472D6549442D536572766572A72431"
// +"2204204FCEC231DC0781B48B7C3994FD"
// +"950A162BB6BCF118F6C806F5FF36F29F"
// +"81F4A8");
byte[] certDescription = HexString.hexToBuffer(
"30 82 01 02 06 0A 04 00 7F 00 07 03 01 03 01 "
+ "01 A1 11 0C 0F 54 65 73 74 69 73 73 75 65 72 "
+ "20 47 6D 62 48 A2 1A 13 18 68 74 74 70 3A 2F "
+ "2F 77 77 77 2E 74 65 73 74 69 73 73 75 65 72 "
+ "2E 64 65 A3 0F 0C 0D 54 65 73 74 68 61 75 73 "
+ "20 47 6D 62 48 A4 18 13 16 68 74 74 70 3A 2F "
+ "2F 77 77 77 2E 74 65 73 74 68 61 75 73 2E 64 "
+ "65 A5 81 99 0C 81 96 41 6E 73 63 68 72 69 66 "
+ "74 3A 20 0D 0A 54 65 73 74 68 61 75 73 20 47 "
+ "6D 62 48 0D 0A 51 75 61 6C 69 74 C3 A4 74 73 "
+ "73 74 72 2E 20 31 0D 0A 33 33 31 30 30 20 50 "
+ "61 64 65 72 62 6F 72 6E 0D 0A 0D 0A 45 2D 4D "
+ "61 69 6C 2D 41 64 72 65 73 73 65 3A 20 0D 0A "
+ "6E 70 61 40 74 65 73 74 68 61 75 73 2E 64 65 "
+ "0D 0A 0D 0A 5A 77 65 63 6B 20 64 65 73 20 41 "
+ "75 73 6C 65 73 65 76 6F 72 67 61 6E 67 73 3A "
+ "20 0D 0A 54 65 73 74 20 64 65 72 20 54 65 72 "
+ "6D 69 6E 61 6C 73 2E");
short certDescLen = (short) certDescription.length;
byte[] dataLength = new byte[] {(byte) (certDescLen & 0xFF), (byte) ((certDescLen & 0xFF00)>>8)};
ByteArrayOutputStream s = new ByteArrayOutputStream();
s.write((byte)0x03); //Password = PIN
s.write(chatLen); // Length CHAT
s.write(chat);
s.write((byte)0x00); //Length PIN
s.write(dataLength);
s.write(certDescription);
byte[] paceInputData = s.toByteArray();
short paceInputDataLen = (short) paceInputData.length;
s = new ByteArrayOutputStream();
s.write((byte)0x02);
byte[] inputDataLength = new byte[] {(byte) (paceInputDataLen & 0xFF), (byte) ((paceInputDataLen & 0xFF00)>>8)};
s.write(inputDataLength);
s.write(paceInputData);
byte[] paceWithPIN = s.toByteArray();
System.out.println(HexString.bufferToHex(paceWithPIN));
byte[] getReaderCapabilities = new byte[] { 0x01, 0, 0 };
byte[] paceWithCAN = new byte[] { 0x02, 5, 0, 0x02, 0,0,0,0};
byte[] resp = card.transmitControlCommand(0x313730, paceWithPIN);
System.out.println("<- " + HexString.bufferToHex(resp));
}
static boolean isWindows() {
String os_name = System.getProperty("os.name").toLowerCase();
if (os_name.indexOf("windows") > -1)
return true;
return false;
}
static int SCARD_CTL_CODE(int code) {
int ioctl;
if (isWindows()) {
ioctl = (0x31 << 16 | (code) << 2);
} else {
ioctl = 0x42000000 + (code);
}
return ioctl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment