PIN格式
ANSI X9.8 Format(带主帐号信息)
PIN BLOCK 格式等于 PIN 按位异或主帐号:
PIN 格式:
BYTE 1 PIN的长度
BYTE 2 – BYTE 3/4/5/6/7 4--12个PIN(每个PIN占4个BIT)
BYTE 4/5/6/7/8 – BYTE 8 FILLER “F” (每个“F“占4个BIT)
主帐号格式:
BYTE 1 — BYTE 2 0X0000
BYTE 3 — BYTE 8 12个主帐号
12位主帐号的取法:取主帐号的右12位(不包括最右边的校验位),不足12位左补“0X00”。
例如:明文 PIN 123456,
设:磁卡上的主帐号为:123456789012345678
截取下的主帐号为:678901234567 则
用于PIN加密的主帐号为:0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
则 PIN BLOCK 为 0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF
异或 0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
结果为 0x06 0x12 0x53 0xDF 0xFE 0xDC 0xBA 0x98
设:磁卡上的主帐号为:1234567890123456
截取下的主帐号为:456789012345
则用于PIN加密的主帐号为:0x00 0x00 0x45 0x67 0x89 0x01 0x23 0x45
则 PIN BLOCK 为 0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF
异或 0x00 0x00 0x45 0x67 0x89 0x01 0x23 0x45
结果为 0x06 0x12 0x71 0x31 0x76 0xFE 0xDC 0xBA
? PIN 加密解密
省中心(外围系统)在发送消息给全国中心(省中心)之前,
应用本中心的PIK对PIN加密后发往全国中心(省中心)。
/**
* getPinBlock
* 标准ANSI X9.8 Format(带主帐号信息)的PIN BLOCK计算
* PIN BLOCK 格式等于 PIN 按位异或 主帐号;
* @param pin String
* @param accno String
* @return byte[]
*/
private byte[] process(String pin, String accno) {
byte arrAccno[] = getHAccno(accno);
byte arrPin[] = getHPin(pin);
byte arrRet[] = new byte[8];
//PIN BLOCK 格式等于 PIN 按位异或 主帐号;
for (int i = 0; i < 8; i++) {
arrRet[i] = (byte) (arrPin[i] ^ arrAccno[i]);
}
Util.printHexString("PinBlock:", arrRet);
return arrRet;
}
/**
* getHPin
* 对密码进行转换
* PIN格式
* BYTE 1 PIN的长度
* BYTE 2 – BYTE 3/4/5/6/7 4--12个PIN(每个PIN占4个BIT)
* BYTE 4/5/6/7/8 – BYTE 8 FILLER “F” (每个“F“占4个BIT)
* @param pin String
* @return byte[]
*/
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;
}
/**
* getHAccno
* 对帐号进行转换
* BYTE 1 — BYTE 2 0X0000
* BYTE 3 — BYTE 8 12个主帐号
* 取主帐号的右12位(不包括最右边的校验位),不足12位左补“0X00”。
* @param accno String
* @return byte[]
*/
private byte[] getHAccno(String accno) {
//取出主帐号;
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;
}