Java解析银联报文_Java生成银联PIN BLOCK

本文介绍了如何使用Java实现银联报文的PIN BLOCK生成,包括PIN的格式填充、主账号处理,以及SM4加密过程。通过提供的`UnionPayUtil`类,可以将PIN和主账号转化为符合银联规范的PIN BLOCK,并进行SM4加密操作。
摘要由CSDN通过智能技术生成

import org.apache.commons.codec.binary.Hex;

import org.apache.commons.lang3.StringUtils;

import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

/**

* 银联工具包

*/

public class UnionPayUtil {

private static final int PIN_MIN_LENGTH = 4;

private static final int PIN_MAX_LENGTH = 12;

private static final int HEXADECIMAL = 16;

/**

* DES/3SDE算法PIN BLOCK大小为8

* SM4算法PIN BLOCK大小为16

*/

private static final int PIN_BLOCK_SIZE = 16;

/**

* 生成 PIN Block

* @param pin

* @return

*/

private static byte[] pinBlock(String pin) {

int pinLength = pin.length();

if (pinLength < PIN_MIN_LENGTH || pinLength > PIN_MAX_LENGTH) {

throw new IllegalArgumentException("Pin should be 4 to 12 digits long");

}

/**

* PIN 格式 16BYTE 大小

* 1BYTE PIN长度 + 15BYTE Pin

* Pin不足部分右补F

*/

byte[] pinBlock = new byte[PIN_BLOCK_SIZE];

//如果是奇数右补F转换成如果不足12位右补F,补到12位长度

pin = StringUtils.rightPad(pin,PIN_MAX_LENGTH,'F');

//先处理PIN BLOCK 长度

pinBlock[0] = (byte) pinLength;

//处理PIN

for (int i = 0; i <= pin.length() - 1; i = i + 2) {

int pinBlockIndex = (i / 2) + 1;

pinBlock[pinBlockIndex] = (byte) Integer.parseInt(pin.substring(i, i + 2), HEXADECIMAL);

}

/**

* 不足32位补,需要补的位长度为PinBlock减去PIN长度域的长度和PIN数据长度

*/

int blockIndex = (pin.length() / 2) + 1;

for (int i = blockIndex; i <= PIN_BLOCK_SIZE - 1; i++) {

pinBlock[i] = (byte) 0xFF;

}

return pinBlock;

}

/**

* 格式

* 2BYTE %H0000

* 14BYTE 取主账号的右12位(不包括最右边的校验位),主账号不足12位左补0

*

* @param mAccNo 主账号

* @return

*/

private static byte[] pan(String mAccNo) {

/**

* 不足12位左补0,后面要取右12位,不包括校验位,全长是不足13位的就需要补

*/

StringUtils.leftPad(mAccNo, 13, '0');

byte[] panByte = new byte[PIN_BLOCK_SIZE];

//截取右12位,包括校验位是13位

String pan = StringUtils.left(StringUtils.right(mAccNo, 12 + 1), 12);

/**

* 2BYTE %H0000

* 14BYTE 取主账号的右12位(不包括最右边的校验位),主账号不足12位左补0

*/

//初始化左边为0区域

int leftSize = PIN_BLOCK_SIZE - 12 / 2;

for (int i = 0; i <= leftSize - 1; i++) {

panByte[i] = (byte) 0x00;

}

int panIndex = 0;

for (int i = leftSize; i <= PIN_BLOCK_SIZE - 1; i++, panIndex+=2) {

String a = pan.substring(panIndex, panIndex + 2);

panByte[i] = (byte) Integer.parseInt(a, HEXADECIMAL);

}

return panByte;

}

/**

* SM4加密,并进行转16进制计算

*

* @return

*/

public static String encryptPin(String accNo, String pin, String key) {

byte[] pinBlock = null;

try {

pinBlock = pinBlock(pin, accNo);

byte[] keyBytes = ByteUtils.fromHexString(key);

pinBlock = SM4Helper.encrypt(keyBytes,pinBlock);

return ByteUtils.toHexString(pinBlock);

} catch (Exception e) {

return "";

}

}

/**

* @param pin Personal Identification Number

* @param mAccNo Main account number

* @return

*/

private static byte[] pinBlock(String pin, String mAccNo) {

byte[] pingBlock = pinBlock(pin);

byte[] pan = pan(mAccNo);

byte[] tByte = new byte[PIN_BLOCK_SIZE];

for (int i = 0; i < PIN_BLOCK_SIZE; i++) {

tByte[i] = (byte) (pingBlock[i] ^ pan[i]);

}

return tByte;

}

public static void main(String[] args) {

String key = "11111111111111111111111111111111";

String pin = "123456";

String accNo = "123456789012345678";

String pinBlock = Hex.encodeHexString(pinBlock(pin, accNo));

System.out.println(pinBlock);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值