转载请注明出处:http://blog.csdn.net/yyh352091626/article/details/51751120

本文详细讲解银联标准MAC算法的过程,以及通过Java代码来实现这一运算过程。

POS终端采用ECB的加密方式,简述如下:

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

8、Java代码实现Mac算法过程如下:

package com.yuyh.keydemo;/*** 银联标准Mac 算法*/
public class MacEcbUtils {public static void main(String[] args) {byte[] key = new byte[]{0x5C, (byte) 0xBE, 0x7E, 0x38, (byte) 0xA1, 0x46, (byte) 0xFD, 0x5C};byte[] input = new byte[]{0x01, 0x02, 0x03};System.out.println(Utils.bcd2Str(getMac(key, input)));}/*** mac计算** @param key   mac秘钥* @param Input 待加密数据* @return*/public static byte[] getMac(byte[] key, byte[] Input) {int length = Input.length;int x = length % 8;// 需要补位的长度int addLen = 0;if (x != 0) {addLen = 8 - length % 8;}int pos = 0;// 原始数据补位后的数据byte[] data = new byte[length + addLen];System.arraycopy(Input, 0, data, 0, length);byte[] oper1 = new byte[8];System.arraycopy(data, pos, oper1, 0, 8);pos += 8;// 8字节异或for (int i = 1; i < data.length / 8; i++) {byte[] oper2 = new byte[8];System.arraycopy(data, pos, oper2, 0, 8);byte[] t = bytesXOR(oper1, oper2);oper1 = t;pos += 8;}// 将异或运算后的最后8个字节(RESULT BLOCK)转换成16个HEXDECIMAL:byte[] resultBlock = bytesToHexString(oper1).getBytes();// 取前8个字节MAK加密byte[] front8 = new byte[8];System.arraycopy(resultBlock, 0, front8, 0, 8);byte[] behind8 = new byte[8];System.arraycopy(resultBlock, 8, behind8, 0, 8);byte[] desfront8 = DesUtils.encrypt(front8, key);// 将加密后的结果与后8 个字节异或:byte[] resultXOR = bytesXOR(desfront8, behind8);// 用异或的结果TEMP BLOCK 再进行一次单倍长密钥算法运算byte[] buff = DesUtils.encrypt(resultXOR, key);// 将运算后的结果(ENC BLOCK2)转换成16 个HEXDECIMAL ascbyte[] retBuf = new byte[8];// 取8个长度字节就是mac值System.arraycopy(bytesToHexString(buff).getBytes(), 0, retBuf, 0, 8);return retBuf;}/*** 单字节异或** @param src1* @param src2* @return*/public static byte byteXOR(byte src1, byte src2) {return (byte) ((src1 & 0xFF) ^ (src2 & 0xFF));}/*** 字节数组异或** @param src1* @param src2* @return*/public static byte[] bytesXOR(byte[] src1, byte[] src2) {int length = src1.length;if (length != src2.length) {return null;}byte[] result = new byte[length];for (int i = 0; i < length; i++) {result[i] = byteXOR(src1[i], src2[i]);}return result;}/*** 字节数组转HEXDECIMAL** @param bArray* @return*/public static final String bytesToHexString(byte[] bArray) {StringBuffer sb = new StringBuffer(bArray.length);String sTemp;for (int i = 0; i < bArray.length; i++) {sTemp = Integer.toHexString(0xFF & bArray[i]);if (sTemp.length() < 2)sb.append(0);sb.append(sTemp.toUpperCase());}return sb.toString();}
}
package com.yuyh.keydemo;import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;/*** DES 加解密*/
public class DesUtils {private final static String DES = "DES";private final static String CIPHER_ALGORITHM = "DES/ECB/NoPadding";/*** 加密** @param src 数据源* @param key 密钥,长度必须是8的倍数* @return 返回加密后的数据*/public static byte[] encrypt(byte[] src, byte[] key) {SecureRandom sr = new SecureRandom();try {DESKeySpec dks = new DESKeySpec(key);SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);SecretKey securekey = keyFactory.generateSecret(dks);Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);return cipher.doFinal(src);} catch (Exception e) {}return null;}/*** 生成密钥** @return* @throws NoSuchAlgorithmException*/public static byte[] initKey() throws NoSuchAlgorithmException {KeyGenerator kg = KeyGenerator.getInstance(DES);kg.init(16);SecretKey secretKey = kg.generateKey();return secretKey.getEncoded();}/*** 解密** @param src 数据源* @param key 密钥,长度必须是8的倍数* @return 返回解密后的原始数据*/public static byte[] decrypt(byte[] src, byte[] key) {SecureRandom sr = new SecureRandom();try {DESKeySpec dks = new DESKeySpec(key);SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);SecretKey securekey = keyFactory.generateSecret(dks);Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, securekey, sr);return cipher.doFinal(src);} catch (Exception e) {}return null;}}
package com.yuyh.keydemo;/*** bcd码 与 String 转化*/
public class Utils {public static String bcd2Str(byte[] b) {char[] HEX_DIGITS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};StringBuilder sb = new StringBuilder(b.length * 2);for (int i = 0; i < b.length; ++i) {sb.append(HEX_DIGITS[(b[i] & 240) >>> 4]);sb.append(HEX_DIGITS[b[i] & 15]);}return sb.toString();}public static byte[] str2Bcd(String asc) {int len = asc.length();int mod = len % 2;if (mod != 0) {asc = "0" + asc;len = asc.length();}byte[] abt = new byte[len];if (len >= 2) {len /= 2;}byte[] bbt = new byte[len];abt = asc.getBytes();for (int p = 0; p < asc.length() / 2; ++p) {int j;if (abt[2 * p] >= 97 && abt[2 * p] <= 122) {j = abt[2 * p] - 97 + 10;} else if (abt[2 * p] >= 65 && abt[2 * p] <= 90) {j = abt[2 * p] - 65 + 10;} else {j = abt[2 * p] - 48;}int k;if (abt[2 * p + 1] >= 97 && abt[2 * p + 1] <= 122) {k = abt[2 * p + 1] - 97 + 10;} else if (abt[2 * p + 1] >= 65 && abt[2 * p + 1] <= 90) {k = abt[2 * p + 1] - 65 + 10;} else {k = abt[2 * p + 1] - 48;}int a = (j << 4) + k;byte b = (byte) a;bbt[p] = b;}return bbt;}
}

银联标准之MAC算法实现(POS终端加密)相关推荐

  1. 首款搭载通过银联标准检测的金融数字化服务终端操作系统相关智能

    近日,搭载江苏润和软件股份有限公司(以下简称"润和软件")研发的金融数字化服务终端操作系统银联标准版.由福建升腾资讯有限公司进行终端适配集成的 K9 型智能 POS 终端,通过了银 ...

  2. 计算机切换到标准用户,Mac电脑使用:终端的管理员用户和普通用户的自由切换方式...

    作为一名IT民工来说,对于电脑的各种操作都需要熟练掌握,不仅要学会Windows电脑的操作,更要学会Mac电脑的操作,不同的操作系统,有些操作是不一样的,就拿终端命令行来说,Windows系统的cmd ...

  3. 【转】POS终端MAC算法

    [转]POS终端MAC算法 原文地址:http://blog.csdn.net/artmcu/article/details/8183406 本文根据<中国银联直联POS终端规范>的阐述, ...

  4. POS DES MAC 算法

    DES和MAC加解密算法,已经在多个产品中得到了实际应用,不需任何修改就可使用 本文根据<中国银联直联POS终端规范>的阐述,用C语言编程实现,该算法在实际的商业POS终端中使用.POS终 ...

  5. 银联Pos终端签到、签退、批结算、批上送、PinKey、MacKey、KEK、主密钥、工作密钥、TPDU、报文头

    原文: http://blog.csdn.net/lvxiangan/article/details/41014439 加密密钥:KEK,terminal keys encrypting key; K ...

  6. 移动支付之Pos终端主密钥、工作密钥、pin密钥、mac密钥

    下面介绍一下加密机中最主要的几种密钥: 1.加密机主密钥(MK) 加密机主密钥(Master Key - MK)是存入在HSM机内的由三个成分合成的一对最上层密钥.在HSM机器以外的地方不会以明文形式 ...

  7. Pos终端中的主密钥、工作密钥、pin密钥、mac密钥

    下面介绍一下加密机中最主要的几种密钥: 1.加密机主密钥(MK) 加密机主密钥(Master Key - MK)是存入在HSM机内的由三个成分合成的一对最上层密钥.在HSM机器以外的地方不会以明文形式 ...

  8. 银联Iso8583报文 POS终端报文结构

    终端则 (一)   基础知识 1byte = 8bit 1byte = 2个16进制数 BCD码:用4位二进制数来表示1位十进制数中的0~9这10个数码,即1bcd码=4bit (二)   报文结构 ...

  9. 银联Pos终端签到、签退、批结算、批上送

    签到:获取pinkey.mackey.批次号 签退:先批结算,然后签退,否则批次号不会更新. 批结算:上送本地pos终端交易流水给服务端,若通过校验则可以进行签退,否则需要批上送交易明细 批上送:批结 ...

  10. MAC算法原理与常用实现

    看本文前,最好先看看之前的对于MD5算法和SHA算法的介绍. 本文目录 定义 常见应用场景 1.linux客户端:SecureCRT 2.Google身份验证器 3.银联pos机终端 原理 java实 ...

最新文章

  1. 010_TreeMap键使用Comparator排序
  2. 不懂电脑如何买电脑_买电脑交智商税?5分钟看懂笔记本电脑配置
  3. 关于js弹出框的介绍:
  4. SecureCRT 中文显示乱码
  5. webstorm比较文件差异
  6. 【java入门】超基础的java入门知识,细节拉满
  7. Intouch高级报警(报警筛选)
  8. 一键磨皮插件:DR5白金版(支持ps 2022)中文版
  9. 最新!2019 年中国程序员薪资生存调查报告出炉
  10. 我的专业我的梦作文计算机,我的创新我的梦优秀作文
  11. python当前运行目录_Python获取运行目录与当前脚本目录的方法
  12. 【零基础跑项目】20代码教你基于opencv的人脸检测
  13. Nevron 3DChart创建有吸引力的3D和2D图表
  14. 美国加州伯克利大学计算机专业排名,美国加州大学伯克利分校计算机专业排名...
  15. Linux配置系统网络(动态)
  16. web-view和runtime.openURL的方式进行外部链接
  17. 十二个一的朝堂江湖大梦
  18. 将excel转成PDF导出
  19. Part2:面向对象、原型链、函数、ES6基础语法
  20. matlab ct投影数据,3.医学影像系统实验-CT投影数据采集、反投影重建实验.ppt

热门文章

  1. oracle临时表怎么删除吗,删除Oracle临时表
  2. Delphi ADOQuery
  3. 【 jvm-sandbox-repeater】环境搭建部署
  4. IDEA中jclasslib插件修改本地化语言为英文的方法
  5. php是哪种币,php有哪些【货币问答】- php有哪些所有答案 - 联合货币
  6. Next主题 - 图片设置
  7. 新鲜出炉,程序员年度薪酬排行榜
  8. ubuntu 20.04 | 美化主题、图标、光标、壁纸、登录背景
  9. 深入理解设计模式之模板模式
  10. 学校做计算机教室锐捷,锐捷网络云课堂:让学生爱上每一节课