银联pinBlock算法的实现

银联PINBLOCK算法的实现,算法规则参考pos销售终端规范(如有需要,可联系博主索取或自行百度,本文仅上实现)

偶然翻到之前写的对于ANSI X9.8标准获取PINBlOCK,发现可能之前比较仓促,并没有对整个过程描述的比较清楚,特意重新整理了下实现,添加对应注释以便于理解该过程。

1.格式化PIN(ANSI X9.8分为带主账号信息与不带主账号信息,如果不带主账号信息那么下面函数处理后返回的即为PINBLOCK)

/**
     * 格式化PIN
     *
     * @param pin
     * @return
     */
   public static byte[] formatPinByX98(byte[] pin) {
        //pin长度
        int l = pin.length;
        //pin合法性检查,规范要求PIN长度为4-12
        if (l < 4 || l > 12) {
            throw new RuntimeException("pin长度错误");
        }
        //固定为8字节长度
        byte[] encode = new byte[8];
        //规范要求不足8自己后补F,先提前补好填充内容方便后面处理
        Arrays.fill(encode, (byte) 0xFF);
        //第一位为pin长度
        encode[0] = (byte) l;
        //计算填充剩余字节(填充规则,按照BCD压缩码填充,即一个字节可以表示2位密码
        // 这里因为一个字节长度为8位,密码确定为0-9中任意数字,这代表用4bit即可完全表示一位密码,所以一个字节可以表示两位密码。
        // 需要注意的是为无符号位的字节,所以填充前我们需要运用按位运算与0x0F运算去掉符号位)
        int cl = l / 2;
        for (int i = 0; i < cl; i++) {
            encode[i + 1] = (byte) ((pin[i * 2] & 0x0F) << 4 | pin[i * 2 + 1] & 0x0F);
            if (i == cl - 1) {
                if ((l & 1) != 0) {
                    //如果传入密码为奇数位,因为上面计算长度整除丢失一位,所以循环到最后一位的时候需要判断传入的pin字节数组长度是否为奇数位
                    //如果为奇数位则需要填充上最后一位密码
                    encode[i + 2] = (byte) ((pin[l - 1] & 0x0F) << 4 | 0x0F);
                }
            }
        }
        return encode;
    }

 

 

 

 

 

2.下面为处理主账号信息

/**
     * 格式化PAN
     *
     * @param pan
     * @return
     */
    private byte[] formartPan(byte[] pan) {
        //PAN合法性检查,规范要求PIN长度为12
        if (pan.length != 12) {
            throw new RuntimeException("PAN长度错误");
        }
        //固定为8字节长度
        byte[] encode = new byte[8];
        int cl = pan.length / 2;
        //前面2字节固定填充为0x00
        encode[0] = 0x00;
        encode[1] = 0x00;
        //计算填充剩余字节(填充规则,按照BCD压缩码填充,即一个字节可以表示2位卡号(原因同PIN)
        for (int i = 0; i < cl; i++) {
            encode[i + 2] = (byte) ((pan[i * 2] & 0x0F) << 4 | pan[i * 2 + 1] & 0x0F);
        }
        return encode;

    }

 

3.下面为调用上面两个函数异或后获取带主账号信息的PINBLOCK(ANSI X9.8分带主账号信息)

        byte[] pan = formartPan(pan);
        byte[] pin = formatPinByX98(pin);
        for (int i = 0; i < pin.length; i++) {//异或
            pin[i] ^= pan[i];
        }
        //异或完后执行加密,以下逻辑可根据自己实际需求处理

 

经过上面运算得到明文的PINBLOCK,然后通过PIN密钥加密就可以得到密文PINBLOCK

 

以上函数 传入的   pan  和 pin  均为ASCII。

 

转载请注明出处!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值