之前自己在网上找相关算法找不到,最后只能自己实现,现在把实现的内容分享给大家,大家可以参考,因为文档不全,所以不完全准确,但在已有环境验证过。

/**

* 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-国密)相关推荐

  1. java常见的hash算法_常见的哈希算法和用途

    写在前面 哈希算法经常会被用到,比如我们Go里面的map,Java的HashMap,目前最流行的缓存Redis都大量用到了哈希算法.它们支持把很多类型的数据进行哈希计算,我们实际使用的时候并不用考虑哈 ...

  2. java 线性回归算法_线性搜索或顺序搜索算法在Java中如何工作? 示例教程

    java 线性回归算法 大家好,之前,我讨论了二进制搜索算法的工作原理,并分享了在Java中实现二进制搜索的代码. 在那篇文章中,有人问我是否还有其他搜索算法? 如果数组中的元素未排序,又该如何使用它 ...

  3. 6种java垃圾回收算法_被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解...

    一.概况 理解Java虚拟机垃圾回收机制的底层原理,是系统调优与线上问题排查的基础,也是一个高级Java程序员的基本功,本文就针对Java垃圾回收这一主题做一些整理与记录.Java垃圾回收器的种类繁多 ...

  4. java 寻路算法_游戏中的寻路算法解析

    游戏角色的自动寻路,已经是游戏中一个历史比较悠久的领域,较为成熟也有很多种实现.这里摘录一句后面所提的参考资料中的描述:"业内AI开发者中有一句话:"寻路已不是问题."我 ...

  5. java信息安全性_java-信息安全(二十)国密算法 SM1,SM2,SM3,SM4

    一.概述 国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位.目前主要使用公开的SM2.SM3.SM4三类算法,分别是非对称算法.哈希算法和对称算 ...

  6. python自带的对称算法_一种基于对称算法和专用加载模块的Python程序模块加密方法...

    一种基于对称算法和专用加载模块的Python程序模块加密方法 [专利说明]一种基于对称算法和专用加载模块的Python程序模块加密方法 技术领域 [0001]本发明涉及一种网络安全技术,具体涉及一种P ...

  7. k均值算法 二分k均值算法_如何获得K均值算法面试问题

    k均值算法 二分k均值算法 数据科学访谈 (Data Science Interviews) KMeans is one of the most common and important cluste ...

  8. ios笔试题算法_微软笔试题-Dijkstra算法

    Dijkstra算法是典型的算法.Dijkstra算法是很有代表性的算法.Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临 ...

  9. 图像 异常检测算法_检测图像异常的算法

    图像 异常检测算法 Modern applications are generating enormous amounts of image data. And in the last years, ...

  10. 最小径集的算法_机器学习的利器——集成算法

    最近在打算法竞赛的时候用到了集成算法,效果还不错,索性就总结了一篇集成算法的文章,希望能帮到正在转行的数据分析师们. 集成算法核心思想 集成算法的核心思想是通过构建并结合多个学习器来完成学习任务,也就 ...

最新文章

  1. 安装Ubuntu server并实现远程访问
  2. 浙大python判断两个字符串是否为变位词_python数据结构与算法 变位词
  3. 机器学习-Kmeans聚类
  4. [C++ Mind Map] class and memory
  5. SAP ui5 xml view parse and control creation point
  6. 【转】azure认证路线以及学习资源
  7. eclipse中项目内存溢出问题
  8. python数据清理_Python-数据清理
  9. android微信支付坑,微信支付踏坑之旅
  10. 2.15_graph_图
  11. gerrit配置replication插件
  12. python路线图_Python路线图
  13. 从统计显著性到显著性统计
  14. 服务器 raid配置
  15. 2022年终总结与2023新年展望
  16. PX4 FMU [17] stabilize
  17. 编个故事,骗700元的稿费真容易啊!
  18. HTML5期末大作业:旅游网页设计与实现——四川成都-(9页 带购物车)
  19. 使用Spring实现AOP的三种方式
  20. matlab:曲线拟合

热门文章

  1. 查看文件夹和文件大小
  2. ITEXT-PDF彩色字体显示-支持中文
  3. 线性分类器——Fisher线性判别
  4. R语言之dpqr概率函数
  5. Datagrid,DataList,Repeate等的数据格式设置表达式
  6. 《自抗扰控制技术》——第二遍(仿真)
  7. Python多字段排序之cmp_to_key详解
  8. 5.9拉普拉斯矩阵的谱分解,谱图卷积,图卷积演变过程
  9. matlab实现螺旋谱分解,MATLAB实现EMD分解及希尔伯特谱分析
  10. 安固士科技——“智慧工地”的核心技术是什么?