JAVA中pin什么意思_银行业加密算法,PIN相关算法(java-国密)

该博客介绍了JAVA中PIN加密的相关算法,包括使用国密SM4进行PIN明文加密和解密的详细过程。文章提供了一系列静态方法,用于PIN的加密、解密以及PIN校验等操作,涉及到IBM3624计算自然PIN、PIN偏移量计算和校验。
摘要由CSDN通过智能技术生成

public class PIN {

/**

* 加密PIN明文

*

* @param pin

* @param pan

* @param key

* @return

* @throws InvalidKeyException

* @throws NoSuchAlgorithmException

* @throws NoSuchProviderException

* @throws NoSuchPaddingException

* @throws ShortBufferException

* @throws IllegalBlockSizeException

* @throws BadPaddingException

* @throws InvalidAlgorithmParameterException

* @throws InvalidKeySpecException

* @throws IllegalArgumentException

* @throws SecurityException

* @throws IOException

*/

public static String encrypt(String pin, String pan, String pik)

throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,

ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,

InvalidKeySpecException, IllegalArgumentException, SecurityException, IOException {

return encrypt(pin, pan, pik, PINFormat.ANSIX98);

}

public static String encrypt(String pin, String pan, String pik, PINFormat format)

throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,

ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,

InvalidKeySpecException, IllegalArgumentException, SecurityException, IOException {

String pinBlock = Format.formatPin(pin, pan, format);

byte[] cipherPin = SM4.encryptECB(Convert.hexToByte(pik), Convert.hexToByte(pinBlock));

return Convert.byteToHexStr(cipherPin);

}

/**

* 解密pin密文

*

* @param pinBlock

* @param pan

* @param key

* @return

* @throws InvalidKeyException

* @throws NoSuchAlgorithmException

* @throws NoSuchProviderException

* @throws NoSuchPaddingException

* @throws ShortBufferException

* @throws IllegalBlockSizeException

* @throws BadPaddingException

* @throws InvalidAlgorithmParameterException

* @throws InvalidKeySpecException

* @throws IllegalArgumentException

* @throws SecurityException

* @throws IOException

*/

public static String decrypt(String pinBlock, String pan, String pik)

throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,

ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,

InvalidKeySpecException, IllegalArgumentException, SecurityException, IOException {

return decrypt(pinBlock, pan, pik, PINFormat.ANSIX98);

}

public static String decrypt(String pinBlock, String pan, String pik, PINFormat format)

throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,

ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,

InvalidKeySpecException, IllegalArgumentException, SecurityException, IOException {

byte[] cipherPin = SM4.decryptECB(Convert.hexToByte(pik), Convert.hexToByte(pinBlock));

String pin = Format.formatPinBack(Convert.byteToHexStr(cipherPin), pan, format);

return pin;

}

/**

* 字符pin加密

*

* @param pin

* @param pik

* @return

* @throws InvalidKeyException

* @throws NoSuchAlgorithmException

* @throws NoSuchProviderException

* @throws NoSuchPaddingException

* @throws ShortBufferException

* @throws IllegalBlockSizeException

* @throws BadPaddingException

* @throws InvalidAlgorithmParameterException

* @throws InvalidKeySpecException

* @throws IllegalArgumentException

* @throws SecurityException

* @throws IOException

*/

public static String encryptCharPin(String pin, String pik)

throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,

ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,

InvalidKeySpecException, IllegalArgumentException, SecurityException, IOException {

String pinBlock = Format.formatPin(pin, pin, PINFormat.CHARPIN);

byte[] cipherPin = SM4.encryptECB(Convert.hexToByte(pinBlock), Convert.hexToByte(pik));

return Convert.byteToHexStr(cipherPin);

}

/**

* 字符pin解密

*

* @param pinBlock

* @param pik

* @return

* @throws InvalidKeyException

* @throws NoSuchAlgorithmException

* @throws NoSuchProviderException

* @throws NoSuchPaddingException

* @throws ShortBufferException

* @throws IllegalBlockSizeException

* @throws BadPaddingException

* @throws InvalidAlgorithmParameterException

* @throws InvalidKeySpecException

* @throws IllegalArgumentException

* @throws SecurityException

* @throws IOException

*/

public static String decryptCharPin(String pinBlock, String pik)

throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,

ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,

InvalidKeySpecException, IllegalArgumentException, SecurityException, IOException {

byte[] cipherPin = SM4.decryptECB(Convert.hexToByte(pinBlock), Convert.hexToByte(pik));

String pin = Format.formatPinBack(Convert.byteToHexStr(cipherPin), "", PINFormat.CHARPIN);

return pin;

}

//计算pinoffset的10进制对照表

public static final String D_TABLE = "0123456789012345";

/**

* IBM3624计算自然PIN

*

* @param pan

* @param pinLength

* @param pvk

* @return

* @throws SecurityException

* @throws InvalidKeyException

* @throws NoSuchAlgorithmException

* @throws NoSuchProviderException

* @throws NoSuchPaddingException

* @throws ShortBufferException

* @throws IllegalBlockSizeException

* @throws BadPaddingException

* @throws InvalidAlgorithmParameterException

* @throws InvalidKeySpecException

* @throws IOException

*/

public static String calculateNaturalPin(String pan, int pinLength, String pvk)

throws SecurityException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,

NoSuchPaddingException, ShortBufferException, IllegalBlockSizeException, BadPaddingException,

InvalidAlgorithmParameterException, InvalidKeySpecException, IOException {

String formatPan = String.format("%-16s", pan).replace(' ', 'F');

byte[] cipherPan = SM4.encryptECB(Convert.hexToByte(formatPan), Convert.hexToByte(pvk));

String cpStr = Convert.byteToHexStr(cipherPan);

StringBuilder builder = new StringBuilder("");

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

builder.append(D_TABLE.charAt(Integer.parseInt(cpStr.substring(i, i + 1), 16)));

}

return builder.toString();

}

/**

* ibm3624计算pinoffset

*

* @param pan

* @param pin

* @param pinLength

* @param pvk

* @return

* @throws Exception

*/

public static String calculatePINOffset(String pan, String pin, int pinLength, String pvk) throws Exception {

if (pin.length() != pinLength) {

throw new SecurityException("bad pinLength");

}

String natrualPin = calculateNaturalPin(pan, pinLength, pvk);

StringBuilder builder = new StringBuilder("");

int cpin;

int npin;

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

cpin = Integer.parseInt(pin.substring(i, i + 1));

npin = Integer.parseInt(natrualPin.substring(i, i + 1));

builder.append(Integer.toString(cpin >= npin ? cpin - npin : 10 + cpin - npin));

}

return builder.toString();

}

/**

* ibm3624校验pin

*

* @param pan

* @param pin

* @param pinLength

* @param offset

* @param pvk

* @return

* @throws Exception

*/

public static boolean validatePINOffset(String pan, String pin, int pinLength, String offset, String pvk)

throws Exception {

if (pin.length() != pinLength) {

throw new SecurityException("bad pinLength");

}

String natrualPin = calculateNaturalPin(pan, pinLength, pvk);

StringBuilder builder = new StringBuilder("");

int opin;

int npin;

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

opin = Integer.parseInt(offset.substring(i, i + 1));

npin = Integer.parseInt(natrualPin.substring(i, i + 1));

builder.append(Integer.toString(opin + npin >= 10 ? opin + npin - 10 : opin + npin));

}

return builder.toString().equals(pin);

}

public static void main(String[] args) throws Exception {

System.out.println(String.format("%-14s", "11").replace(" ", "F"));

String pinc = encrypt("123456", "123456789012345678",

"0123456789ABCDEF0123456789ABCDEF");

System.out.println(pinc);

// ;

// System.out.println(decrypt(pinc, "123456789012345678",

// "0123456789ABCDEF0123456789ABCDEF"));

System.out.println(calculatePINOffset("1234567899876543", "3096", 4, "0123456789ABCDEFFEDCBA9876543210"));

System.out

.println(validatePINOffset("1234567899876543", "3096", 4, "0900", "0123456789ABCDEFFEDCBA9876543210"));

System.out.println(encryptCharPin("oracle9i", "0123456789ABCDEFFEDCBA9876543210"));

System.out.println(decryptCharPin("1E716BD9406500C9B8D9F178DCD52F26058AAFCE50FDFC69", "0123456789ABCDEFFEDCBA9876543210"));

}

}

对应pin格式化帮助类

/**

* https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.csfb400/pinbf.htm

* 参考以上链接-IBM Knowledge Center

* PIN 格式化

*

* P = 一个4位十进制数字,是PIN值的一位数。 C = 一个4位十六进制控制值。有效值为X'0',X'1'和X'2'。 L =

* 一个4位十六进制值,指定PIN数字的数量。值范围为4到12,包括4和12。 F = 值为X'F'的 4位字段定界符。 f =

* 一个4位分隔符填充符,它是P或F,具体取决于PIN的长度。 D = 一个4位十进制填充值。PIN块中的所有填充数字具有相同的值。 X =

* 一个4位十六进制填充值。PIN块中的所有填充数字具有相同的值。 x = 一个4位十六进制填充符,它是P或X,具体取决于PIN的长度。 R =

* 一个4位十六进制随机数字。R位的序列可以各自取不同的值。 r = 4位随机填充,P或R,取决于PIN的长度。 Z = 一个4位十六进制零(X'0')。 z

* = 一个4位零填充,可以是P或Z,具体取决于PIN的长度。 S = 一个4位十六进制数字,构成序列号的一位数。 A =

* 一个4位十进制数字,构成用户指定常量的一位数。

*

* @author Administrator

*

*/

public class Format {

/**

* ANSI X9.8/ISO0/VISA1/VISA4/ECI1

*

* P1 = CLPPPPffffffffFF P2 = ZZZZAAAAAAAAAAAA PIN Block = P1 XOR P2 where C =

* X'0' L = X'4' to X'C'

*

* https://max.book118.com/html/2017/0907/132467659.shtm

* 中国银联银行卡交换系统技术规范(国际卷)第4部分

* https://max.book118.com/html/2015/0713/20968185.shtm

*

* PIN域:共64bit,每4bit为1位十六进制数字,共16位十六进制数字 第1位(1~4bit):固定值0x0(0000)

* 第2位(5~8bit):PIN长度,取值范围0x4(0100) ~ 0xC(1100)

* 第3~16位(9~64bit):PIN,不足14位右补0xF(1111),因为PIN最多12位,所以最后2位一定是0xFF(1111,1111)

*

* PAN域:共64bit,每4bit为1位十六进制数字,共16位十六进制数字

* 第1~4位(1~16bit):固定值0x0000(0000,0000,0000,0000)

* 第5~16位(17~64bit):PAN,去掉最右边1位校验数字后,从右边数12位,不足12位左补0x0(0000)

*

* @param pin

* 密码

* @param pan

* 账号

* @return Format 0 PIN block 十六进制字符串

* @throws SecurityException

*/

private static String formatPin0(String pin, String pan) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN域,64bit,16位十六进制数字

// 固定值0x0 + PIN长度 + PIN(不足14位右补F)

String PINField = "0" + Integer.toHexString(pin.length()) + String.format("%-14s", pin).replace(' ', 'F');

// PAN域,64bit,16位十六进制数字

// 固定值0x0000 + PAN,去掉校验数字,从右边数12位,不足12位左补0x0

String PANWithoutCheckDigit = pan.substring(0, pan.length() - 1);

String PANField = "0000" + (PANWithoutCheckDigit.length() > 12

? PANWithoutCheckDigit.substring(PANWithoutCheckDigit.length() - 12, PANWithoutCheckDigit.length())

: String.format("%12s", PANWithoutCheckDigit).replace(' ', '0'));

// 十六进制转byte数组

byte[] PINFieldByteArray = Convert.hexToByte(PINField);

// 十六进制转byte数组

byte[] PANFieldByteArray = Convert.hexToByte(PANField);

// 异或

byte[] PINBlockByteArray = new byte[8];

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

PINBlockByteArray[i] = (byte) (PINFieldByteArray[i] ^ PANFieldByteArray[i]);

}

// 返回十六进制

return Convert.byteToHexStr(PINBlockByteArray).toUpperCase();

}

private static String formatPin0Back(String pinBlock, String pan) throws SecurityException {

// 十六进制转byte数组

byte[] pinBlockByteArray = Convert.hexToByte(pinBlock);

// 十六进制转byte数组

String PANWithoutCheckDigit = pan.substring(0, pan.length() - 1);

String PANField = "0000" + (PANWithoutCheckDigit.length() > 12

? PANWithoutCheckDigit.substring(PANWithoutCheckDigit.length() - 12, PANWithoutCheckDigit.length())

: String.format("%12s", PANWithoutCheckDigit).replace(' ', '0'));

byte[] panByteArray = Convert.hexToByte(PANField);

// 异或

byte[] pinByteArray = new byte[8];

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

pinByteArray[i] = (byte) (pinBlockByteArray[i] ^ panByteArray[i]);

}

String pinBlockStr = Convert.byteToHexStr(pinByteArray);

int lengh = Integer.parseInt(pinBlockStr.substring(1, 2), 16);

return pinBlockStr.substring(2, 2 + lengh);

}

/**

* ISO1/ECI4

*

* PIN Block = CLPPPPrrrrrrrrRR where C = X'1' L = X'4' to X'C'

*

* @param PIN

* @return

* @throws SecurityException

*/

private static String formatPin1(String pin) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位右补交易域

String PINBlock = "1" + Integer.toHexString(pin.length()) + pin;

// 交易域使用随机数,取值范围是0x0~0xF

Random r = new Random();

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

PINBlock += Integer.toHexString(r.nextInt(16));

}

return PINBlock.toUpperCase();

}

private static String formatPin1Back(String pinBlock) {

int length = Integer.parseInt("" + pinBlock.charAt(1), 16);

return pinBlock.substring(2, 2 + length);

}

/**

* ISO2

*

* PIN Block = CLPPPPffffffffFF where C = X'2' L = X'4' to X'C'

*

* @param PIN

* @return

* @throws SecurityException

*/

private static String formatPin2(String pin) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位0xF

String PINBlock = "2" + Integer.toHexString(pin.length()) + String.format("%-14s", pin).replace(' ', 'F');

return PINBlock.toUpperCase();

}

private static String formatPin2Back(String pinBlock) {

int length = Integer.parseInt("" + pinBlock.charAt(1), 16);

return pinBlock.substring(2, 2 + length);

}

/**

* ISO3

*

* P1 = CLPPPPrrrrrrrrRR P2 = ZZZZAAAAAAAAAAAA PIN Block = P1 XOR P2 where C =

* X'3' L = X'4' to X'C'

*

* @param pin

* @param pan

* @return

* @throws SecurityException

*/

private static String formatPin3(String pin, String pan) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位右补交易域

String PINField = "3" + Integer.toHexString(pin.length()) + pin;

// 交易域使用随机数,取值范围是0x0~0xF

Random r = new Random();

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

PINField += Integer.toHexString(r.nextInt(16));

}

// PAN域,64bit,16位十六进制数字

// 固定值0x0000 + PAN,去掉校验数字,从右边数12位,不足12位左补0x0

String PANWithoutCheckDigit = pan.substring(0, pan.length() - 1);

String PANField = "0000" + (PANWithoutCheckDigit.length() > 12

? PANWithoutCheckDigit.substring(PANWithoutCheckDigit.length() - 12, PANWithoutCheckDigit.length())

: String.format("%12s", PANWithoutCheckDigit).replace(' ', '0'));

// 十六进制转byte数组

byte[] PINFieldByteArray = Convert.hexToByte(PINField);

// 十六进制转byte数组

byte[] PANFieldByteArray = Convert.hexToByte(PANField);

// 异或

byte[] PINBlockByteArray = new byte[8];

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

PINBlockByteArray[i] = (byte) (PINFieldByteArray[i] ^ PANFieldByteArray[i]);

}

// 返回十六进制

return Convert.byteToHexStr(PINBlockByteArray).toUpperCase();

}

private static String formatPin3Back(String pinBlock, String pan) throws SecurityException {

// PAN域,64bit,16位十六进制数字

// 固定值0x0000 + PAN,去掉校验数字,从右边数12位,不足12位左补0x0

String PANWithoutCheckDigit = pan.substring(0, pan.length() - 1);

String PANField = "0000" + (PANWithoutCheckDigit.length() > 12

? PANWithoutCheckDigit.substring(PANWithoutCheckDigit.length() - 12, PANWithoutCheckDigit.length())

: String.format("%12s", PANWithoutCheckDigit).replace(' ', '0'));

// 十六进制转byte数组

byte[] PINFieldByteArray = Convert.hexToByte(pinBlock);

// 十六进制转byte数组

byte[] PANFieldByteArray = Convert.hexToByte(PANField);

// 异或

byte[] PINBlockByteArray = new byte[8];

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

PINBlockByteArray[i] = (byte) (PINFieldByteArray[i] ^ PANFieldByteArray[i]);

}

String pb = Convert.byteToHexStr(PINBlockByteArray);

int length = Integer.parseInt("" + pb.charAt(1), 16);

return pb.substring(2, 2 + length);

}

/**

* VISA2

*

* PIN Block = LPPPPzzDDDDDDDDD where L = X'4' to X'6'

*

* @param pin

* @return

* @throws SecurityException

*/

private static String formatPin4(String pin) throws SecurityException {

if (pin.length() > 6 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位十进制9

String PINBlock = "" + Integer.toHexString(pin.length()) + String.format("%-6s", pin).replace(' ', '0')

+ "999999999";

return PINBlock.toUpperCase();

}

private static String formatPin4Back(String pinBlock) {

int length = Integer.parseInt("" + pinBlock.charAt(0), 16);

return pinBlock.substring(1, 1 + length);

}

/**

* visa3

*

* PIN Block = PPPPPPFXXXXXXXXX

*

* @param pin

* @return

* @throws SecurityException

*/

private static String formatPin5(String pin) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位十进制9

String PINBlock = pin + "F";

while (PINBlock.length() < 16) {

PINBlock += "9";

}

return PINBlock.toUpperCase();

}

private static String formatPin5Back(String pinBlock) {

int length = pinBlock.indexOf("F");

return pinBlock.substring(0, length);

}

/**

* IBM4700

*

* PIN Block = LPPPPffffffffFSS where L = X'4' to X'C'

*

* @param pin

* @return

* @throws SecurityException

*/

private static String formatPin6(String pin) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位十进制9

String PINBlock = "" + Integer.toHexString(pin.length()) + String.format("%-12s", pin).replace(' ', '9')

+ "F00";

for (int i = PINBlock.length(); i < 16; i++) {

PINBlock += "9";

}

return PINBlock.toUpperCase();

}

private static String formatPin6Back(String pinBlock) {

int length = Integer.parseInt("" + pinBlock.charAt(0), 16);

return pinBlock.substring(1, 1 + length);

}

/**

* IBM3624

*

* PIN Block = PPPPxxxxxxxxXXXX

*

* @param pin

* @return

* @throws SecurityException

*/

private static String formatPin7(String pin) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位十进制9

String PINBlock = String.format("%-16s", pin).replace(' ', 'F');

return PINBlock.toUpperCase();

}

private static String formatPin7Back(String pinBlock) {

int length = pinBlock.indexOf("F");

return pinBlock.substring(0, length);

}

/**

* IBM3621

*

* PIN Block = SSSSPPPPxxxxxxxx

*

* @param pin

* @return

* @throws SecurityException

*/

private static String formatPin8(String pin) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位十进制9

String PINBlock = "0000" + String.format("%-14s", pin).replace(' ', 'A');

return PINBlock.toUpperCase();

}

private static String formatPin8Back(String pinBlock) {

int length = pinBlock.indexOf("A");

return pinBlock.substring(4, length);

}

/**

* ECI2

*

* PIN Block = PPPPRRRRRRRRRRRR

*

* @param pin

* @return

* @throws SecurityException

*/

private static String formatPin9(String pin) throws SecurityException {

if (pin.length() != 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位十进制9

String PINBlock = pin;

Random r = new Random();

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

PINBlock += Integer.toHexString(r.nextInt(16));

}

return PINBlock.toUpperCase();

}

private static String formatPin9Back(String pinBlock) {

return pinBlock.substring(0, 4);

}

/**

* ECI3

*

* PIN Block = LPPPPzzRRRRRRRRR where L = X'4' to X'6'

*

* @param pin

* @return

* @throws SecurityException

*/

private static String formatPin10(String pin) throws SecurityException {

if (pin.length() > 6 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN block,64bit,16位十六进制数字

// 固定值0x1 + PIN长度 + PIN,不足14位十进制9

String PINBlock = "" + Integer.toHexString(pin.length()) + String.format("%-6s", pin).replace(' ', '0');

Random r = new Random();

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

PINBlock += Integer.toHexString(r.nextInt(16));

}

return PINBlock.toUpperCase();

}

private static String formatPin10Back(String pinBlock) {

int length = Integer.parseInt(pinBlock.substring(0, 1), 16);

return pinBlock.substring(1, 1 + length);

}

/**

* 格式化字符PIN

* @param charPin

* @return

* @throws SecurityException

*/

private static String formatCharPin(String charPin) throws SecurityException {

if(charPin.length() > 20 || charPin.length() < 6) {

throw new SecurityException("bad pin");

}

String pinBlock = "";

//长度以10进制8byte字符标识

if(charPin.length() < 16) {

pinBlock += ("0" + Integer.toHexString(charPin.length()));

}else {

pinBlock += Integer.toHexString(charPin.length());

}

//总长24位,不足填充F

pinBlock += String.format("%-22s", charPin).replace(' ', 'F');

byte[] pbByte = ASCII.stringToByteArr(pinBlock);

return Convert.byteToHexStr(pbByte);

}

private static String formatCharPinBack(String charPinBlock) throws SecurityException {

byte[] pbByte = Convert.hexToByte(charPinBlock);

String pinBlock = new String(ASCII.byteArrToCharArr(pbByte));

return pinBlock.substring(2, 2 + Integer.parseInt(pinBlock.substring(0, 2), 16));

}

private static String formatPinGM(String pin, String pan) throws SecurityException {

if (pin.length() > 12 || pin.length() < 4) {

throw new SecurityException("bad pin");

}

// PIN域,64bit,16位十六进制数字

// 固定值0x0 + PIN长度 + PIN(不足14位右补F)

String PINField = "0" + Integer.toHexString(pin.length()) + String.format("%-30s", pin).replace(' ', 'F');

// PAN域,64bit,16位十六进制数字

// 固定值0x0000 + PAN,去掉校验数字,从右边数12位,不足12位左补0x0

String PANWithoutCheckDigit = pan.substring(0, pan.length() - 1);

String PANField = "00000000000000000000" + (PANWithoutCheckDigit.length() > 12

? PANWithoutCheckDigit.substring(PANWithoutCheckDigit.length() - 12, PANWithoutCheckDigit.length())

: String.format("%12s", PANWithoutCheckDigit).replace(' ', '0'));

// 十六进制转byte数组

byte[] PINFieldByteArray = Convert.hexToByte(PINField);

// 十六进制转byte数组

byte[] PANFieldByteArray = Convert.hexToByte(PANField);

// 异或

byte[] PINBlockByteArray = new byte[16];

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

PINBlockByteArray[i] = (byte) (PINFieldByteArray[i] ^ PANFieldByteArray[i]);

}

// 返回十六进制

return Convert.byteToHexStr(PINBlockByteArray).toUpperCase();

}

private static String formatPinGMBack(String pinBlock, String pan) throws SecurityException {

// 十六进制转byte数组

byte[] pinBlockByteArray = Convert.hexToByte(pinBlock);

// 十六进制转byte数组

String PANWithoutCheckDigit = pan.substring(0, pan.length() - 1);

String PANField = "00000000000000000000" + (PANWithoutCheckDigit.length() > 12

? PANWithoutCheckDigit.substring(PANWithoutCheckDigit.length() - 12, PANWithoutCheckDigit.length())

: String.format("%12s", PANWithoutCheckDigit).replace(' ', '0'));

byte[] panByteArray = Convert.hexToByte(PANField);

// 异或

byte[] pinByteArray = new byte[16];

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

pinByteArray[i] = (byte) (pinBlockByteArray[i] ^ panByteArray[i]);

}

String pinBlockStr = Convert.byteToHexStr(pinByteArray);

int lengh = Integer.parseInt(pinBlockStr.substring(1, 2), 16);

return pinBlockStr.substring(2, 2 + lengh);

}

/**

* 格式化PIN

*

* @param pin

* @param pan

* @param format

* @return

* @throws SecurityException

*/

public static String formatPin(String pin, String pan, PINFormat format) throws SecurityException {

String pinBlock = "";

switch (format) {

case ANSIX98:

case ISO0:

case VISA1:

case VISA4:

case ECI1:

pinBlock = formatPin0(pin, pan);

break;

case ISO1:

case ECI4:

pinBlock = formatPin1(pin);

break;

case ISO2:

pinBlock = formatPin2(pin);

break;

case ISO3:

pinBlock = formatPin3(pin, pan);

break;

case VISA2:

pinBlock = formatPin4(pin);

break;

case VISA3:

pinBlock = formatPin5(pin);

break;

case IBM4700:

pinBlock = formatPin6(pin);

break;

case IBM3624:

pinBlock = formatPin7(pin);

break;

case IBM3621:

pinBlock = formatPin8(pin);

break;

case ECI2:

pinBlock = formatPin9(pin);

break;

case ECI3:

pinBlock = formatPin10(pin);

break;

case CHARPIN:

pinBlock = formatCharPin(pin);

break;

case GMANSI98:

pinBlock = formatPinGM(pin, pan);

break;

default:

break;

}

return pinBlock;

}

/**

* 反解PIN

*

* @param pin

* @param pan

* @param format

* @return

* @throws SecurityException

*/

public static String formatPinBack(String pinBlock, String pan, PINFormat format) throws SecurityException {

String pin = "";

switch (format) {

case ANSIX98:

case ISO0:

case VISA1:

case VISA4:

case ECI1:

pin = formatPin0Back(pinBlock, pan);

break;

case ISO1:

case ECI4:

pin = formatPin1Back(pinBlock);

break;

case ISO2:

pin = formatPin2Back(pinBlock);

break;

case ISO3:

pin = formatPin3Back(pinBlock, pan);

break;

case VISA2:

pin = formatPin4Back(pinBlock);

break;

case VISA3:

pin = formatPin5Back(pinBlock);

break;

case IBM4700:

pin = formatPin6Back(pinBlock);

break;

case IBM3624:

pin = formatPin7Back(pinBlock);

break;

case IBM3621:

pin = formatPin8Back(pinBlock);

break;

case ECI2:

pin = formatPin9Back(pinBlock);

break;

case ECI3:

pin = formatPin10Back(pinBlock);

break;

case CHARPIN:

pin = formatCharPinBack(pinBlock);

break;

case GMANSI98:

pin = formatPinGMBack(pinBlock, pan);

break;

default:

break;

}

return pin;

}

public static void main(String[] args) throws SecurityException {

String pin = "851019";

String pan = "6225881297078266";

System.out.println(formatPin0(pin, pan));

//PINFormat[] ps = PINFormat.values();

//for (PINFormat pinFormat : ps) {

//if(PINFormat.ECI2 == pinFormat || PINFormat.CHARPIN == pinFormat) {

//continue;

//}

//String pinBlock = formatPin(pin, pan, pinFormat);

//System.out.println(pinBlock);

//System.out.println(formatPinBack(pinBlock, pan, pinFormat));

//System.out.println();

//}

//String pinBlock = formatPin("oracle9i", pan, PINFormat.CHARPIN);

//System.out.println(pinBlock);

//System.out.println(formatPinBack(pinBlock, pan, PINFormat.CHARPIN));

//System.out.println();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值