天天看点

ANSI X9.8

  (1) ANSI X9.8 Format(不带主账号信息 )

      位置                  长度                              说明

       1                      1byte                          PIN的长度

       2                      7byte                         6-12位PIN(每个字符占4个BIT,不足8位右补F)

例如:明文PIN为 123456,

则PIN BLOCK为 0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF

(2)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加密后发往全国中心(省中心)。

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;

}

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) {

    //取出主帐号;

    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;

}