java mac算法_银行业加密算法,MAC算法算法(java-国密)
之前自己在网上找相关算法找不到,最后只能自己实现,现在把实现的内容分享给大家,大家可以参考,因为文档不全,所以不完全准确,但在已有环境验证过。
/**
* 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++]);
mac[7] = (byte) (mac[7] ^ paddingData[i++]);
mac[8] = (byte) (mac[8] ^ paddingData[i++]);
mac[9] = (byte) (mac[9] ^ paddingData[i++]);
mac[10] = (byte) (mac[10] ^ paddingData[i++]);
mac[11] = (byte) (mac[11] ^ paddingData[i++]);
mac[12] = (byte) (mac[12] ^ paddingData[i++]);
mac[13] = (byte) (mac[13] ^ paddingData[i++]);
mac[14] = (byte) (mac[14] ^ paddingData[i++]);
mac[15] = (byte) (mac[15] ^ paddingData[i++]);
mac = SM4.encryptECB(key, mac);
}
return mac;
}
public static byte[] calculateANSIX9_9MAC(String data, byte[] key)
throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,
InvalidKeySpecException, SecurityException, IOException {
return calculateANSIX9_9MAC(data.getBytes(), key);
}
/**
* 采用ANSI x9.19算法计算MAC (Count MAC by ANSI-x9.19).
* 将ANSI X9.9的结果做如下计算
* (6) 用MAC密钥右半部解密(5)的结果。
* (7) 用MAC密钥左半部加密(6)的结果。
* (8) 取(7)的结果的左半部作为MAC。
*
* @param key
* 16字节密钥数据
* @param data
* 待计算的缓冲区
* @throws SecurityException
* @throws InvalidKeySpecException
* @throws InvalidAlgorithmParameterException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws ShortBufferException
* @throws NoSuchPaddingException
* @throws NoSuchProviderException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws IOException
* @throws GeneralSecurityException
*/
public static byte[] calculateANSIX9_19MAC(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");
}
return calculateANSIX9_9MAC(data, key);
}
public static byte[] calculateANSIX9_19MAC(String data, byte[] key)
throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,
InvalidKeySpecException, SecurityException, IOException {
return calculateANSIX9_19MAC(data.getBytes(), key);
}
/**
* 银联POS
* 1、将欲发送给POS中心的消息中,从消息类型(MTI)到63域之间的部分构成MAC ELEMEMENT BLOCK (MAB)
* 2、对MAB,按每8个字节做异或(不管信息中的字符格式),如果最后不满8个字节,则添加“0x00” 下面举个例子来说明MAC算法的过程: MAB = M1
* M2 M3 M4 (假设MAB有M1,M2,M3,M4这四块构成,每块8字节) M1 = MS11 MS12 MS13 MS14 MS15 MS16
* MS17 MS18 M2 = MS21 MS22 MS23 MS24 MS25 MS26 MS27 MS28 M3 = MS31 MS32 MS33
* MS34 MS35 MS36 MS37 MS38 M4 = MS41 MS42 MS43 MS44 MS45 MS46 MS47 MS48
* 1、按如下规则进行异或运算(每8个字节进行异或最后得到8字节的结果) (1)MS11 MS12 MS13 MS14 MS15 MS16 MS17 MS18
* (xor) MS21 MS22 MS23 MS24 MS25 MS26 MS27 MS28 = TM11 TM12 TM13 TM14 TM15 TM16
* TM17 TM18 (2)TM11 TM12 TM13 TM14 TM15 TM16 TM17 TM18 (xor)MS31 MS32 MS33 MS34
* MS35 MS36 MS37 MS38 = TM21 TM22 TM23 TM24 TM25 TM26 TM27 TM28 (3)TM21 TM22
* TM23 TM24 TM25 TM26 TM27 TM28(xor)MS41 MS42 MS43 MS44 MS45 MS46 MS47 MS48 =
* TM31 TM32 TM33 TM34 TM35 TM36 TM37 TM38 2、最后我们可以得到TM31 TM32 TM33 TM34 TM35
* TM36 TM37 TM38这8个字节,转换成16 个HEXDECIMAL TM31 TM32 TM33 TM34 TM35 TM36 TM37 TM38
* ==> TM311 TM312 TM321 TM322 TM331 TM332 TM341 TM342 TM351 TM352 TM361 TM362
* TM371 TM372 TM381 TM382 3、然后取这16 个HEXDECIMAL的前8个字节,用MAK进行DES加密(或者3DES加密)
* eMAK(TM311 TM312 TM321 TM322 TM331 TM332 TM341 TM342) = EN11 EN12 EN13 EN14
* EN15 EN16 EN17 EN18 4、将加密后的结果与6 个HEXDECIMAL的后8个字节进行异或运算 EN11 EN12 EN13 EN14
* EN15 EN16 EN17 EN18 (xor) TM351 TM352 TM361 TM362 TM371 TM372 TM381 TM382 =
* TE11 TE12 TE13 TE14 TE15 TE16 TE17 TE18 5、再将异或的结果进行一次单倍长的秘钥算法运算 eMAK(TE11
* TE12 TE13 TE14 TE15 TE16 TE17 TE18) = EN21 EN22 EN23 EN24 EN25 EN26 EN27 EN28
* 6、然后将加密运算后的结果,转换成16 个HEXDECIMAL EN21 EN22 EN23 EN24 EN25 EN26 EN27 EN28 ==>
* EM211 EM212 EM221 EM222 EM231 EM232 EM241 EM242 EM251 EM252 EM261 EM262
*
* EM271 EM272 EM281 EM282 7、最后,取16 个HEXDECIMAL的前8个字节,就是MAC值。 result = EM211
* EM212 EM221 EM222 EM231 EM232 EM241 EM242
*
*
* @param key
* @param data
* @return
* @throws InvalidKeyException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
* @throws NoSuchPaddingException
* @throws ShortBufferException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeySpecException
* @throws SecurityException
* @throws IOException
*/
public static byte[] calculateCUPPosMAC(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException, NoSuchPaddingException, ShortBufferException, IllegalBlockSizeException,
BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException, SecurityException, IOException {
int dataLength = data.length;
byte[] paddingData = new byte[(dataLength & 0xF) == 0 ? dataLength : (dataLength + 8) & 0xFFFFFFF0];
System.arraycopy(data, 0, paddingData, 0, dataLength);
byte[] mac = new byte[16];
System.arraycopy(paddingData, 0, mac, 0, 16);
for (int i = 16; 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++]);
mac[7] = (byte) (mac[7] ^ paddingData[i++]);
mac[8] = (byte) (mac[8] ^ paddingData[i++]);
mac[9] = (byte) (mac[9] ^ paddingData[i++]);
mac[10] = (byte) (mac[10] ^ paddingData[i++]);
mac[11] = (byte) (mac[11] ^ paddingData[i++]);
mac[12] = (byte) (mac[12] ^ paddingData[i++]);
mac[13] = (byte) (mac[13] ^ paddingData[i++]);
mac[14] = (byte) (mac[14] ^ paddingData[i++]);
mac[15] = (byte) (mac[15] ^ paddingData[i++]);
}
byte[] xoResult = ASCII.stringToByteArr(Convert.byteToHexStr(mac));
byte[] left = new byte[16];
System.arraycopy(xoResult, 0, left, 0, 16);
byte[] right = new byte[16];
System.arraycopy(xoResult, 16, right, 0, 16);
byte[] e1 = SM4.encryptECB(key, left);
e1[0] = (byte) (e1[0] ^ right[0]);
e1[1] = (byte) (e1[1] ^ right[1]);
e1[2] = (byte) (e1[2] ^ right[2]);
e1[3] = (byte) (e1[3] ^ right[3]);
e1[4] = (byte) (e1[4] ^ right[4]);
e1[5] = (byte) (e1[5] ^ right[5]);
e1[6] = (byte) (e1[6] ^ right[6]);
e1[7] = (byte) (e1[7] ^ right[7]);
e1[8] = (byte) (e1[8] ^ right[8]);
e1[9] = (byte) (e1[9] ^ right[9]);
e1[10] = (byte) (e1[10] ^ right[10]);
e1[11] = (byte) (e1[11] ^ right[11]);
e1[12] = (byte) (e1[12] ^ right[12]);
e1[13] = (byte) (e1[13] ^ right[13]);
e1[14] = (byte) (e1[14] ^ right[14]);
e1[15] = (byte) (e1[15] ^ right[15]);
byte[] e2 = SM4.encryptECB(key, e1);
return e2;
}
public static void main(String[] args) throws Exception {
//验证calculateCUPPosMAC接口
//String data = "asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgasdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgasdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgasdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgasdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgjkuiyui";
String key = "0123456789ABCDEFFEDCBA9876543210";
//byte[] b = calculateCUPPosMAC(Convert.hexToByte(data), Convert.hexToByte(key));
//System.out.println(Convert.byteToHex(b));
//验证calculateANSIX9_9MAC接口
//data = "0200199559993500000000002000000000000010000070616032100392470110008010200020801020002F4112345F42012345678912";
byte[] b = calculateANSIX9_19MAC("asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgasdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgasdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgasdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgasdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfgjkuiyui".getBytes(), Convert.hexToByte(key));
System.out.println(Convert.byteToHex(b));
//b = calculateANSIX9_9MAC(Convert.hexToByte(data), Convert.hexToByte(key));
//System.out.println(Convert.byteToHex(b));
//
//
//
//int dataLength = 54;
//System.out.println(17 & 0xF);
数据补全
//System.out.println((dataLength & 0xF) == 0 ? dataLength : (((dataLength + 16) >> 4) << 4));
//System.out.println((dataLength & 0x7) == 0 ? dataLength : (((dataLength + 8) >> 3) << 3));
}
}
java mac算法_银行业加密算法,MAC算法算法(java-国密)相关推荐
- java常见的hash算法_常见的哈希算法和用途
写在前面 哈希算法经常会被用到,比如我们Go里面的map,Java的HashMap,目前最流行的缓存Redis都大量用到了哈希算法.它们支持把很多类型的数据进行哈希计算,我们实际使用的时候并不用考虑哈 ...
- java 线性回归算法_线性搜索或顺序搜索算法在Java中如何工作? 示例教程
java 线性回归算法 大家好,之前,我讨论了二进制搜索算法的工作原理,并分享了在Java中实现二进制搜索的代码. 在那篇文章中,有人问我是否还有其他搜索算法? 如果数组中的元素未排序,又该如何使用它 ...
- 6种java垃圾回收算法_被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解...
一.概况 理解Java虚拟机垃圾回收机制的底层原理,是系统调优与线上问题排查的基础,也是一个高级Java程序员的基本功,本文就针对Java垃圾回收这一主题做一些整理与记录.Java垃圾回收器的种类繁多 ...
- java 寻路算法_游戏中的寻路算法解析
游戏角色的自动寻路,已经是游戏中一个历史比较悠久的领域,较为成熟也有很多种实现.这里摘录一句后面所提的参考资料中的描述:"业内AI开发者中有一句话:"寻路已不是问题."我 ...
- java信息安全性_java-信息安全(二十)国密算法 SM1,SM2,SM3,SM4
一.概述 国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位.目前主要使用公开的SM2.SM3.SM4三类算法,分别是非对称算法.哈希算法和对称算 ...
- python自带的对称算法_一种基于对称算法和专用加载模块的Python程序模块加密方法...
一种基于对称算法和专用加载模块的Python程序模块加密方法 [专利说明]一种基于对称算法和专用加载模块的Python程序模块加密方法 技术领域 [0001]本发明涉及一种网络安全技术,具体涉及一种P ...
- k均值算法 二分k均值算法_如何获得K均值算法面试问题
k均值算法 二分k均值算法 数据科学访谈 (Data Science Interviews) KMeans is one of the most common and important cluste ...
- ios笔试题算法_微软笔试题-Dijkstra算法
Dijkstra算法是典型的算法.Dijkstra算法是很有代表性的算法.Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临 ...
- 图像 异常检测算法_检测图像异常的算法
图像 异常检测算法 Modern applications are generating enormous amounts of image data. And in the last years, ...
- 最小径集的算法_机器学习的利器——集成算法
最近在打算法竞赛的时候用到了集成算法,效果还不错,索性就总结了一篇集成算法的文章,希望能帮到正在转行的数据分析师们. 集成算法核心思想 集成算法的核心思想是通过构建并结合多个学习器来完成学习任务,也就 ...
最新文章
- 安装Ubuntu server并实现远程访问
- 浙大python判断两个字符串是否为变位词_python数据结构与算法 变位词
- 机器学习-Kmeans聚类
- [C++ Mind Map] class and memory
- SAP ui5 xml view parse and control creation point
- 【转】azure认证路线以及学习资源
- eclipse中项目内存溢出问题
- python数据清理_Python-数据清理
- android微信支付坑,微信支付踏坑之旅
- 2.15_graph_图
- gerrit配置replication插件
- python路线图_Python路线图
- 从统计显著性到显著性统计
- 服务器 raid配置
- 2022年终总结与2023新年展望
- PX4 FMU [17] stabilize
- 编个故事,骗700元的稿费真容易啊!
- HTML5期末大作业:旅游网页设计与实现——四川成都-(9页 带购物车)
- 使用Spring实现AOP的三种方式
- matlab:曲线拟合