概念理解
mac算法是(Message Authentication Codes 消息認(rèn)證碼算法)长踊,是含有密鑰散列函數(shù)算法倘待。主要通過異或運算侯繁,再配合其他加密算法實現(xiàn)mac值的運算挂据,用于校驗以清。
實現(xiàn)方式
-
將要計算的數(shù)據(jù)通過轉(zhuǎn)換成16進(jìn)制字符串
如:
數(shù)據(jù):woshiceshishujuwoshiceshishujuwoshiceshishuju
轉(zhuǎn)成16進(jìn)制:
776F73686963657368697368756A75776F73686963657368697368756A75776F73686963657368697368756A75
-
根據(jù)一定的規(guī)則補位,用于下一步的分組做準(zhǔn)備,一般保證長度為16的倍數(shù)
補位規(guī)則一般為對16進(jìn)制數(shù)據(jù)字符串長度進(jìn)行mod16取余崎逃,如果為0掷倔,直接在數(shù)據(jù)后邊拼16位的"0000000000000000",如果補位0个绍,規(guī)則就要前后端協(xié)調(diào)一致了勒葱,有的在后邊先拼接"80"然后拼"00",有的直接拼"00"
補位后的數(shù)據(jù):
776F7368 69636573 68697368 756A7577 6F736869 63657368 69736875 6A75776F 73686963 65736869 7368756A 75000000
-
將補位后的數(shù)據(jù)分組
一般16位一組,并將每組數(shù)據(jù)保存在一個數(shù)組中
分組后的數(shù)據(jù):
第0組明文:776F7368 69636573
第1組明文:68697368 756A7577
第2組明文:6F736869 63657368
第3組明文:69736875 6A75776F
第4組明文:73686963 65736869
第5組明文:7368756A 75000000
- 將分組數(shù)據(jù)進(jìn)行異或運算
第0組明文: 776F7368 69636573
第1組明文: 68697368 756A7577
第1組異或結(jié)果(第0組與第1組明文異或): 1F060000 1C091004
第2組明文: 6F736869 63657368
第2組異或結(jié)果(第1組異或結(jié)果與第2組明文異或): 70756869 7F6C636C
第3組明文: 69736875 6A75776F
第3組異或結(jié)果(第2組異或結(jié)果與第3組明文異或): 1906001C 15191403
第4組明文: 73686963 65736869
第4組異或結(jié)果(第3組異或結(jié)果與第4組明文異或): 6A6E697F 706A7C6A
第5組明文: 7368756A 75000000
與第4組密文異或: 19061C15 056A7C6A
-
搭配其他加密算法進(jìn)行加密計算
這個地方可以選擇的加密算法也有很多(如:3Dex巴柿、AES凛虽、RSA等)
將最后結(jié)果轉(zhuǎn)成16進(jìn)制 31393036 31433135 30353641 37433641
將前8個字節(jié)的數(shù)據(jù)進(jìn)行加密(加密算法根據(jù)自己需求)
前8字節(jié)加密結(jié)果: 613A342B ED50BC09
與后8字節(jié)異或結(jié)果:510F026A DA138A48
再加密結(jié)果: 3550F588 19AA72AE
將最后結(jié)果轉(zhuǎn)成16進(jìn)制 33353530 46353838 31394141 37324145
前8字節(jié)作為MAC: 33353530 46353838
MAC(字符串形式):3550F588
代碼實現(xiàn)
-
將要計算的數(shù)據(jù)通過轉(zhuǎn)換成16進(jìn)制字符串
如:
數(shù)據(jù):woshiceshishujuwoshiceshishujuwoshiceshishuju
轉(zhuǎn)成16進(jìn)制:
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();
- 根據(jù)一定的規(guī)則補位,用于下一步的分組做準(zhǔn)備,一般保證長度為16的倍數(shù)
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";
}
}
-
將補位后的數(shù)據(jù)分組
一般16位一組广恢,并將每組數(shù)據(jù)保存在一個數(shù)組中
分組后的數(shù)據(jù):
for (int i = 0; i < arrLen; i++) {
D[i] = data.substring(i * 16, i * 16 + 16);
}
- 將分組數(shù)據(jù)進(jìn)行異或運算
String I = xOr(D[0], vector);
String O = null;
String kl = key.substring(0, 16);
for (int i = 1; i < arrLen; i++) {
//有的會在每次異或前對上次異或的結(jié)果進(jìn)行一次加密凯旋,再進(jìn)行下次異或
// 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;
}
-
搭配其他加密算法進(jìn)行加密計算
這個地方可以選擇的加密算法也有很多(如: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加密算法的實現(xiàn)至非。