ANSI X9.8 Standard PIN xor PAN Get PIN BlOCK
I saw a few introductions before, saying that ANSI is 16 bytes, it is really nonsense, all kinds of mistaken children, the actual ANSI algorithm is actually 8 bytes, the specific format is as follows:
(1) ANSI X9.8 Format (without master account information)
PIN (Personal Identification Number) has a total length of 8 bytes and is divided into two parts; (similar to the format of a data packet)
1: Byte1 records the length of the PIN
2: Byte2-Byte8 6-12 digits (character) PIN (each character occupies 4 BIT, less than 8 digits complement F)
For example: the plain text PIN is 123456,
Then PIN BLOCK is 0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF
0x06 records that the length of the PIN is 6, and the less than 16 bits are filled with F, and then converted to BCD code (BCD code is an 8-bit binary number as a unit, that is, the size of a byte is also a hexadecimal number HEX Occupied length).
(2) ANSI X9.8 Format (with master account information)
PIN BLOCK format: Equal to PIN bitwise XOR master account
PIN format: (similar to the format in 1)
Byte 1 PIN length
Byte 2 – Byte 3/4/5/6/7 4--12 PINs (4 BITs per PIN)
Byte4 / 5/6/7/8 – Byte 8 FILLER “F” (4 for each “F”)
PAN (Primary Account Number) also contains 8 bytes, the format is as follows:
Byte 1 — Byte 2 0x00 0x00
Byte 3 — Byte 8 12 main account characters (the last digit is the check digit)
How to use a 12-character master account: Take the right 12 digits of the master account (excluding the rightmost check digit), and less than 12 digits add "0X00" to the left.
example:
Plain text PIN: 123456,
Primary account number PAN: 123456789012345678
The intercepted master account number is: 678901234567 (the first 12 characters of the last check digit 8 are the intercepted master account number)
The main account used for PIN encryption is: 0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
Then PIN BLOCK (PIN bitwise XOR master account PAN)
That is: 0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF
Exclusive OR: 0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
The result is: 0x06 0x12 0x53 0xDF 0xFE 0xDC 0xBA 0x98
Algorithm source code: (contains a utility class Util and a conversion class ANSIFormat.java)
Util.java
package CodeApe;
public class Util {
public Util () {
}
public static void printHexString (String hint, byte [] b) {
System.out.print (hint);
for (int i = 0; i <b.length; i ++) {
String hex = Integer.toHexString (b [i] & 0xFF);
if (hex.length () == 1) {
hex = ‘0’ + hex;
}
System.out.print (hex.toUpperCase () + "");
}
System.out.println ("");
}
public static String Bytes2HexString (byte [] b) {
String ret = "";
for (int i = 0; i <b.length; i ++) {
String hex = Integer.toHexString (b [i] & 0xFF);
if (hex.length () == 1) {
hex = ‘0’ + hex;
}
ret + = hex.toUpperCase ();
}
return ret;
}
public static byte uniteBytes (byte src0, byte src1) {
byte _b0 = Byte.decode ("0x" + new String (new byte [] {src0}))
.byteValue ();
_b0 = (byte) (_b0 << 4);
byte _b1 = Byte.decode ("0x" + new String (new byte [] {src1}))
.byteValue ();
byte ret = (byte) (_b0 ^ _b1);
return ret;
}
public static byte [] HexString2Bytes (String src) {
byte [] ret = new byte [8];
byte [] tmp = src.getBytes ();
for (int i = 0; i <8; i ++) {
ret [i] = uniteBytes (tmp [i * 2], tmp [i * 2 + 1]);
}
return ret;
}
}
ANSIFormat.java
package CodeApe;
import java.io.ObjectInputStream.GetField;
import javax.annotation.processing.Processor;
import CodeApe.Util;
public class ANSIFormat {
private String pin;
private String accno;
public ANSIFormat (String pin, String accno) {
this.pin = pin;
this.accno = accno;
}
public byte [] process (String pin, String accno) {
byte arrPin [] = getHPin (pin);
byte arrAccno [] = getHAccno (accno);
byte arrRet [] = new byte [8];
// PIN BLOCK format is equal to PIN bitwise XOR main account;
for (int i = 0; i <8; i ++) {
arrRet [i] = (byte) (arrPin [i] ^ arrAccno [i]);
}
Util.printHexString ("PinBlock:", arrRet);
return arrRet;
}
private byte [] getHPin (String pin) {
byte arrPin [] = pin.getBytes ();
byte encode [] = new byte [8];
encode [0] = (byte) 0x06;
encode [1] = (byte) Util.uniteBytes (arrPin [0], arrPin [1]);
encode [2] = (byte) Util.uniteBytes (arrPin [2], arrPin [3]);
encode [3] = (byte) Util.uniteBytes (arrPin [4], arrPin [5]);
encode [4] = (byte) 0xFF;
encode [5] = (byte) 0xFF;
encode [6] = (byte) 0xFF;
encode [7] = (byte) 0xFF;
Util.printHexString ("encoded pin:", encode);
return encode;
}
private byte [] getHAccno (String accno) {
// Remove the main account;
int len = accno.length ();
byte arrTemp [] = accno.substring (len <13? 0: len-13, len-1) .getBytes ();
byte arrAccno [] = new byte [12];
for (int i = 0; i <12; i ++) {
arrAccno [i] = (i <= arrTemp.length? arrTemp [i]: (byte) 0x00);
}
byte encode [] = new byte [8];
encode [0] = (byte) 0x00;
encode [1] = (byte) 0x00;
encode [2] = (byte) Util.uniteBytes (arrAccno [0], arrAccno [1]);
encode [3] = (byte) Util.uniteBytes (arrAccno [2], arrAccno [3]);
encode [4] = (byte) Util.uniteBytes (arrAccno [4], arrAccno [5]);
encode [5] = (byte) Util.uniteBytes (arrAccno [6], arrAccno [7]);
encode [6] = (byte) Util.uniteBytes (arrAccno [8], arrAccno [9]);
encode [7] = (byte) Util.uniteBytes (arrAccno [10], arrAccno [11]);
Util.printHexString ("encoded accno:", encode);
return encode;
}
}
test.java (test class)
package CodeApe;
public class test {
private static ANSIFormat pass;
public static void main (String [] args) {
// TODO Auto-generated method stub
String pin = "123456";
String accno = "123456789012345678";
System.out.println ("encoded pin:" + pin);
System.out.println ("encoded accno:" + accno);
pass = new ANSIFormat (pin, accno);
byte [] b = pass.process (pin, accno);
}
}
:--!
ANSI X9.8 Standard PIN xor PAN Get PIN BlOCK