之前自己在网上找相关算法找不到,最后只能自己实现,现在把实现的内容分享给大家,大家可以参考,因为文档不全,所以不完全准确,但在已有环境验证过。
/**
* mac算法
* @author Administrator
*
* 银联用calculateANSIX9_9MAC
*/
public class MAC {
/**
* ANSI X9.9MAC算法
* (1) ANSI X9.9MAC算法只使用单倍长密钥。
* (2) MAC数据先按8字节分组,表示为D0~Dn,如果Dn不足8字节时,尾部以字节00补齐。
* (3) 用MAC密钥加密D0,加密结果与D1异或作为下一次的输入。
* (4) 将上一步的加密结果与下一分组异或,然后再用MAC密钥加密。
* (5) 直至所有分组结束,取最后结果的左半部作为MAC。
* 采用x9.9算法计算MAC (Count MAC by ANSI-x9.9).
*
* @param key
* 8字节密钥数据
* @param data
* 待计算的缓冲区
* @throws SecurityException
* @throws InvalidKeySpecException
* @throws InvalidAlgorithmParameterException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws ShortBufferException
* @throws NoSuchPaddingException
* @throws NoSuchProviderException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws IOException
*/
public static byte[] calculateANSIX9_9MAC(byte[] data, byte[] key)
throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,
InvalidKeySpecException, SecurityException, IOException {
if (key.length != 16) {
throw new SecurityException("bad parameter key");
}
int dataLength = data.length;
// 数据补全
byte[] paddingData = new byte[(dataLength & 0xF) == 0 ? dataLength : (((dataLength + 16) >> 4) << 4)];
System.arraycopy(data, 0, paddingData, 0, dataLength);
// 分组加密
byte[] mac = new byte[16];
for (int i = 0; i < paddingData.length;) {
mac[0] = (byte) (mac[0] ^ paddingData[i++]);
mac[1] = (byte) (mac[1] ^ paddingData[i++]);
mac[2] = (byte) (mac[2] ^ paddingData[i++]);
mac[3] = (byte) (mac[3] ^ paddingData[i++]);
mac[4] = (byte) (mac[4] ^ paddingData[i++]);
mac[5] = (byte) (mac[5] ^ paddingData[i++]);
mac[6] = (byte) (mac[6] ^ paddingData[i++]);<