java mac pos_pos终端mac国密(sm4)算法(java实现)
概念理解
mac算法是(Message Authentication Codes 消息認(rèn)證碼算法),是含有密鑰散列函數(shù)算法。主要通過異或運算,再配合其他加密算法實現(xiàn)mac值的運算,用于校驗。
實現(xiàn)過程
將需要加密計算的字符串轉(zhuǎn)換為16進制字符串
例如:
密鑰:"12345678901234567890123456789012"
待加密數(shù)據(jù)(字符串形式):
6000112018111411003020170930101010120171025000755000000005553
轉(zhuǎn)化為16進制:
36303030 31313230 31383131 31343131 30303330 32303137 30393330 31303130 31303132 30313731 30323530 30303735 35303030 30303030 30353535 33
將轉(zhuǎn)換過的16字符串進行補位分組
部位后的數(shù)據(jù)(部位規(guī)則:字符長度%32!=0補位)
36303030 31313230 31383131 31343131 30303330 32303137 30393330 31303130 31303132 30313731 30323530 30303735 35303030 30303030 30353535 33000000
分組后的數(shù)據(jù)
第 0組明文:36303030 31313230 31383131 31343131
第 1組明文:30303330 32303137 30393330 31303130
第 2組明文:31303132 30313731 30323530 30303735
第 3組明文:35303030 30303030 30353535 33000000
將分組過的字符串?dāng)?shù)組逐步進行異或運算
異或流程
第 0組明文: 36303030 31313230 31383131 31343131
第 1組明文: 30303330 32303137 30393330 31303130
第 1組異或結(jié)果:06000300 03010307 01010201 00040001
第 2組明文:31303132 30313731 30323530 30303735
第 2組異或結(jié)果:37303232 33303436 31333731 30343734
第3組明文:35303030 30303030 30353535 33000000
與第2組密文異或:02000202 03000406 01060204 03343734
將最后異或結(jié)果轉(zhuǎn)化為16進制字符串
轉(zhuǎn)換為16進制
30323030 30323032 30333030 30343036 30313036 30323034 30333334 33373334
取前16位和后16位,前16位進行sm4加密,加密結(jié)果與后16位異或后再加密
前16位
30323030 30323032 30333030 30343036
后16位
30313036 30323034 30333334 33373334
前16位加密結(jié)果
B038A2B2 F3FFE3C8 AC60B377 C70C2DB1
與后16位異或結(jié)果
80099284 C3CDD3FC 9C538043 F43B1E85
再加密結(jié)果
1E80F373 40B0FEE6 2C81F356 AFB20BF1
取前16個字符作為mac值
mac值:1E80F37340B0FEE6
具體實現(xiàn)過程
準(zhǔn)備工作
數(shù)據(jù)轉(zhuǎn)換工具類 TransferUtils.java
字符串轉(zhuǎn)換為16進制字符串
public static String StringToHexString(String str) {
String data = bytesToHexString(str.getBytes(), 32);
return data;
}
字節(jié)數(shù)組轉(zhuǎn)換為16進制字符串
/**
* 字節(jié)數(shù)組轉(zhuǎn)化為十六進制字符串 并按照len的倍數(shù)進行補"0"
* @param bytes 字節(jié)數(shù)據(jù)
* @param len 部位原則 不夠len倍數(shù)補"0"
* @return
*/
public static String bytesToHexString(byte[] bytes, int len) {
StringBuffer hexStr = new StringBuffer();
for (byte b : bytes) {
hexStr.append(String.format("%02x", new Integer(b & 0xff)));
}
//長度不滿32的整數(shù)倍 在后邊添加 "0"
while (hexStr.length() % len != 0) {
hexStr.append("0");
}
return hexStr.toString();
}
將字符串str 按照長度len 進行分組
/**
* 將字符串str 按照長度len 進行分組
* @param str 字符串
* @param len 每組字符長度
* @return
*/
public static String[] dataGrouping(String str, int len) {
int lenth = str.length() % len == 0 ? str.length() / len : str.length() / len + 1;
String[] data = new String[lenth];
for (int i = 0; i < lenth; i++) {
data[i] = str.substring(i * len, i * len + len);
}
return data;
}
將字符串?dāng)?shù)組進行異或運算
public static String handleXOrStringArr(String[] strs){
String result = "";
for (int i = 1;i < strs.length;i++){
if (i == 1){
result = xOr(strs[0],strs[1]);
}else {
result = xOr(strs[i],result);
}
}
return result;
}
異或運算
/**
* 異或運算
* @param s1
* @param s2
* @return
*/
public static String xOr(String s1, String s2) {
String data = IntArr2String(xOr(String2IntArr(s1),String2IntArr(s2)));
return data;
}
public static int [] xOr(int[] i1,int[] i2){
int[] xor = new int[i1.length];
for (int i = 0;i < i1.length & i < i2.length;i++){
xor[i] = i1[i]^i2[i];
}
return xor;
}
加密工具類
sm4加密
public static byte[] encodeSMS4(byte[] plaintext, byte[] key) {
byte[] ciphertext = new byte[plaintext.length];
int k = 0;
int plainLen = plaintext.length;
while (k + 16 <= plainLen) {
byte[] cellPlain = new byte[16];
for (int i = 0; i < 16; i++) {
cellPlain[i] = plaintext[k + i];
}
byte[] cellCipher = encode16(cellPlain, key);
for (int i = 0; i < cellCipher.length; i++) {
ciphertext[k + i] = cellCipher[i];
}
k += 16;
}
return ciphertext;
}
調(diào)用過程
將密鑰轉(zhuǎn)換為字節(jié)數(shù)組,將需要加密計算的字符串轉(zhuǎn)換為16進制字符串并補位
例如:
密鑰:"12345678901234567890123456789012"
待加密數(shù)據(jù)(字符串形式):
6000112018111411003020170930101010120171025000755000000005553
//將key轉(zhuǎn)換為字節(jié)數(shù)組
byte[] keys = TransformUtils.HexStringToByteArr(key);
//將加密數(shù)據(jù)轉(zhuǎn)換為16進制字符串
String hexData = TransformUtils.StringToHexString(data);
將轉(zhuǎn)換過的16字符串進行分組
//將數(shù)據(jù)分組 32位為一組
String[] dataGroup = TransformUtils.dataGrouping(hexData, 32);
將分組過的字符串?dāng)?shù)組逐步進行異或運算
//進行異或運算
String xorData = TransformUtils.handleXOrStringArr(dataGroup);
將最后異或結(jié)果轉(zhuǎn)化為16進制字符串
//將異或結(jié)果轉(zhuǎn)化為16進制字符串
String hexOxrData = TransformUtils.StringToHexString(xorData);
取前16字節(jié)和后16字節(jié),前16字節(jié)進行sm4加密,加密結(jié)果與后16字節(jié)異或后再加密
//取前16字節(jié)和后16字節(jié) 兩個16進制位表示一個字節(jié)
String start32Bit = hexOxrData.substring(0,32);
String end32Bit = hexOxrData.substring(hexOxrData.length() - 32,hexOxrData.length());
//前16位進行首次加密
byte[] encodeSMS4_1 = SMS4.encodeSMS4(TransformUtils.HexStringToByteArr(start32Bit), keys);
//加密結(jié)果與后16位進行異或
String xOrEnd = TransformUtils.xOr(TransformUtils.bytesToHexString(encodeSMS4_1, 16), end32Bit);
//異或結(jié)果轉(zhuǎn)成字節(jié)數(shù)組
byte[] bytes = TransformUtils.HexStringToByteArr(xOrEnd);
//進行二次加密
byte[] resultByte = SMS4.encodeSMS4(bytes, keys);
//將加密結(jié)果轉(zhuǎn)換成16進制字符串 并取前八個字符作為mac值返回
String result = TransformUtils.bytesToHexString(resultByte, 16);
取前16個字符作為mac值
//取前8字節(jié)作為mac值返回
result = result.substring(0,16);
后記
此處是pos終端mac國密(sm4)算法,之前還有一個pos終端mac國際算法(雙倍長 3des),兩者的區(qū)別在于 分組的時候分組長度不太一樣,國際是16個16進制字符(8字節(jié))分組,國密是32個16進制字符(16字節(jié))分組,再有不同的地方就是加密算法不同,國密是sm4加密算法,國際是雙倍長3des加密算法,其他基本都是一樣的,這個加密算法也是根據(jù)需求可以進行更改的 ,比如改為RSA 或AES也是可以的,這個就需要雙方溝通了 統(tǒng)一加密算法就可以了
總結(jié)
以上是生活随笔為你收集整理的java mac pos_pos终端mac国密(sm4)算法(java实现)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win7 mysql添加到服务_MySQ
- 下一篇: git master代码被删除 怎么恢复