JAVA中pin什么意思_银行业加密算法,PIN相关算法(java-国密)
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();
}
}
JAVA中pin什么意思_银行业加密算法,PIN相关算法(java-国密)相关推荐
- java中解密的思想_北大青鸟翔天解密,Java核心思想两大点
Java已经成为一个庞大而复杂的技术平台,对于开发人员而言,要想更好的掌握Java技术,深入理解底层的技术处理细节必不可少.对核心概念和思想的掌握可以帮助我们举一反三.触类旁通,有助于提升我们对整个J ...
- java中arraycopy的用法_[jdk源码阅读系列]Java中System.arraycopy()的用法
本文转载,原文链接: 3分钟了解Java中System.arraycopy的用法 - 伊万夫斯基 - 博客园 https://www.cnblogs.com/benjieqiang/p/114288 ...
- java中二进制怎么说_面试常用:说清楚Java中synchronized和volatile的区别
回顾一下两个关键字:synchronized和volatile 1.Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized.v ...
- java中Solution怎么用_【leetcode】solution in java——Easy4
16:Invert Binary Tree 此题:以根为对称轴,反转二叉树. 思路:看到二叉树,我们第一时间要想到处理二叉树的常用方法--BFS.DFS,更常用的是DFS.此题我们先用BFS来思考:B ...
- java中异常+连接重置_是什么导致我的java.nett.ocketException:连接重置?
是什么导致我的java.nett.ocketException:连接重置? 我们看到了频繁但断断续续的情况.java.net.SocketException: Connection reset我们日志 ...
- java中sql模糊查询_模糊查询的sql语句(java模糊查询sql语句)
模糊查询的sql语句(java模糊查询sql语句) 2020-07-24 11:06:02 共10个回答 假设表名为product,商品名为name,简界为remark.则可如下写:select[na ...
- java中fork什么意思_最通俗的例子讲解Java中的fork-join
public class SumArray { private static class SumTask extends RecursiveTask{ private final static int ...
- java中execution的作用_一文初步了解Java虚拟机
大家都知道,Java中JVM的重要性,学习了JVM你对Java的运行机制.编译过程和如何对Java程序进行调优相信都会有一个很好的认知. 什么是JVM? JVM(Java Virtual Machin ...
- java中的复合数据类型是什么_【填空题】类是Java中的一种重要的复合数据类型,是组成Java程序的基本要素。一个类的实现包括两部分:____和_____....
[填空题]类是Java中的一种重要的复合数据类型,是组成Java程序的基本要素.一个类的实现包括两部分:____和_____. 更多相关问题 [名词解释] 观叶树木 [单选] 开花时有浓郁香气的树种是 ...
最新文章
- Codeforces Round #643 (Div. 2)题解
- C语言基础知识【数据类型】
- 用python创建数据库监控平台(3)安装Python3.5
- 《基于Node.js实现简易聊天室系列之项目前期工作》
- FreeMarker学习2
- docker学习笔记(六)docker-compose
- AMD院士站台 异构计算与OpenCL编程师资培训首站清华开讲
- 区块链BAAS平台:公共或私人区块链编程以用于各种用途
- selectprovider 分页_MyBatis使用@SelectProvider拼接sql语句
- Spring Boot————单元测试
- 三星开源的 tcpflow 抓包工具
- SAP系统管理员的工作
- echarts 柱状图 横坐标文字纵向展示(超出显示...)
- python学习总结4 - 流程控制工具
- Atitit 学科与知识领域分类门类分类法 目录 1. 学位学科门类是授予学位的学科类别。国际上大体有两种划分方法:	1 2. 三大类法 文理科 医学	1 3. 五大门类	2 4. 13门类	2 5
- 两年数据对比柱形图_【系列课程】用Excel进行数据可视化组合图表的制作lt;二gt;...
- PFC离散元+3DEC离散元技术与应用学习
- C#技术交流④群正式开建,诚邀各路大佬莅临指导
- 小米路由器3G建站折腾笔记6 - 总结
- html文本框打tab,HTML标签textarea支持tab键
热门文章
- python 数组比较大小_python – 比较两个不同长度的numpy数组
- python创建文件对象的函数_Python学习笔记之—— File(文件) 对象常用函数
- unity2d自动生成敌人_【A*Pathfinding】超级简单的Unity2D寻路
- linux下的文档处理及tar命令
- 回顾JavsScript对象的克隆
- 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 三十║ Nuxt实战:动态路由+同构...
- oc基础 不可变字符串的创建和使用
- Excel VBA入门的基础语句
- 利用CUTFTP Tranfer Engine开发.NET FTP客户端
- curl post json_curl 模拟 GETPOST 请求,以及 curl post 上传文件