概念理解
mac算法是(Message Authentication Codes 消息认证码算法),是含有密钥散列函数算法。主要通过异或运算,再配合其他加密算法实现mac值的运算,用于校验。
实现方式
-
将要计算的数据通过转换成16进制字符串
如:
数据:woshiceshishujuwoshiceshishujuwoshiceshishuju
转成16进制:
776F73686963657368697368756A75776F73686963657368697368756A75776F73686963657368697368756A75
-
根据一定的规则补位,用于下一步的分组做准备,一般保证长度为16的倍数
补位规则一般为对16进制数据字符串长度进行mod16取余,如果为0,直接在数据后边拼16位的"0000000000000000",如果补位0,规则就要前后端协调一致了,有的在后边先拼接"80"然后拼"00",有的直接拼"00"
补位后的数据:
776F7368 69636573 68697368 756A7577 6F736869 63657368 69736875 6A75776F 73686963 65736869 7368756A 75000000
-
将补位后的数据分组
一般16位一组,并将每组数据保存在一个数组中
分组后的数据:
第0组明文:776F7368 69636573
第1组明文:68697368 756A7577
第2组明文:6F736869 63657368
第3组明文:69736875 6A75776F
第4组明文:73686963 65736869
第5组明文:7368756A 75000000
- 将分组数据进行异或运算
第0组明文: 776F7368 69636573
第1组明文: 68697368 756A7577
第1组异或结果(第0组与第1组明文异或): 1F060000 1C091004
第2组明文: 6F736869 63657368
第2组异或结果(第1组异或结果与第2组明文异或): 70756869 7F6C636C
第3组明文: 69736875 6A75776F
第3组异或结果(第2组异或结果与第3组明文异或): 1906001C 15191403
第4组明文: 73686963 65736869
第4组异或结果(第3组异或结果与第4组明文异或): 6A6E697F 706A7C6A
第5组明文: 7368756A 75000000
与第4组密文异或: 19061C15 056A7C6A
-
搭配其他加密算法进行加密计算
这个地方可以选择的加密算法也有很多(如:3Dex、AES、RSA等)
将最后结果转成16进制 31393036 31433135 30353641 37433641
将前8个字节的数据进行加密(加密算法根据自己需求)
前8字节加密结果: 613A342B ED50BC09
与后8字节异或结果:510F026A DA138A48
再加密结果: 3550F588 19AA72AE
将最后结果转成16进制 33353530 46353838 31394141 37324145
前8字节作为MAC: 33353530 46353838
MAC(字符串形式):3550F588
代码实现
-
将要计算的数据通过转换成16进制字符串
如:
数据:woshiceshishujuwoshiceshishujuwoshiceshishuju
转成16进制:
StringBuffer hex = new StringBuffer();
try {
byte[] bs = asc.toUpperCase().getBytes("UTF-8");
for (byte b : bs) {
hex.append(Integer.toHexString(new Byte(b).intValue()));
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return hex.toString();
- 根据一定的规则补位,用于下一步的分组做准备,一般保证长度为16的倍数
int len = data.length();
int arrLen = len / 16 + 1;
String[] D = new String[arrLen];
if (len % 16 == 0) {
data += "0000000000000000";
} else {
data += "00";
for (int i = 0; i < 15 - len % 16; i++) {
data += "00";
}
}
-
将补位后的数据分组
一般16位一组,并将每组数据保存在一个数组中
分组后的数据:
for (int i = 0; i < arrLen; i++) {
D[i] = data.substring(i * 16, i * 16 + 16);
}
- 将分组数据进行异或运算
String I = xOr(D[0], vector);
String O = null;
String kl = key.substring(0, 16);
for (int i = 1; i < arrLen; i++) {
//有的会在每次异或前对上次异或的结果进行一次加密,再进行下次异或
// O = DES_1(I, kl, 0);
String str = D[i];
I = xOr(D[i], I);
}
public static String xOr(String s1, String s2) {
int[] iArr = diffOr(string2Binary(s1), string2Binary(s2));
return binary2ASC(intArr2Str(iArr));
}
public static int[] diffOr(int[] source1, int[] source2) {
int len = source1.length;
int[] dest = new int[len];
for (int i = 0; i < len; i++) {
dest[i] = source1[i] ^ source2[i];
}
return dest;
}
-
搭配其他加密算法进行加密计算
这个地方可以选择的加密算法也有很多(如:3Dex、AES、RSA等)
String hex = ASC_2_HEX(I);
String tep1 = hex.substring(0, hex.length()/2);
String tep2 = hex.substring(hex.length()/2, hex.length());
I = DES_3(tep1, key, HEX);
I = xOr(I, tep2);
I = DES_3(I, key, 0);
此处的DES_3()是一个3DES加密算法的实现。