Java实现3DES加密--及ANSI X9.8 Format标准 PIN PAN获取PIN BlOCK
1, 采用银联ANSI X9.8标准 PIN xor PAN获取PIN BlOCK
2, 采用3Des进行加密
参考:
要点:因为3DES是对称加密算法,key是24位,当只有16位时,后8位取key的前8位
ANSI X9.8标准 PIN xor PAN获取PIN BlOCK
(1) ANSI X9.8 Format(不带主账号信息)
PIN(个人识别码 Personal Identity Number)总共有8个byte长度,分为两个部分;(类似数据包的格式)
1:Byte1 记录PIN的长度
2:Byte2-Byte8 6-12位(字符)PIN(每个字符占4个BIT,不足8位右补F)
例如:明文PIN为 123456,
则PIN BLOCK为 0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF
0x06记录了PIN的长度为6,后边不足16位均以F补齐,然后转换为BCD码(BCD码为8位二进制数为一个单元,也就是一个Byte的大小也是一个十六进制数HEX的占用长度)。
(2)ANSI X9.8 Format(带主帐号信息)
PIN BLOCK 格式:等于 PIN 按位异或主帐号
PIN 格式:(与1中的格式类似)
Byte 1 PIN的长度
Byte 2 – Byte 3/4/5/6/7 4--12个PIN(每个PIN占4个BIT)
Byte4/5/6/7/8 – Byte 8 FILLER “F” (每个“F“占4个BIT)
PAN(主帐号 Primary Account Number)同样包含8个byte,格式如下:
Byte 1 — Byte 2 0x00 0x00
Byte 3 — Byte 8 12个主帐号字符(最后一位为校验位)
12位字符主帐号的取法:取主帐号的右12位(不包括最右边的校验位),不足12位左补“0X00”。
例子:
明文 PIN:123456,
主帐号 PAN:123456789012345678
截取下的主帐号为:678901234567 (最后一位校验位8的前12位字符为截取的主帐号)
则用于PIN加密的主帐号为:0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
则 PIN BLOCK (PIN按位异或主帐号PAN)
即是为: 0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF
异或上: 0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
结果为: 0x06 0x12 0x53 0xDF 0xFE 0xDC 0xBA 0x98
--------------------------------------------Java代码的实现-------------------------------
package com.bstek.tools; import java.security.Security; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; /** * 加密 3Des算法实现 *1: A---使用3Des解密B----得到C *2:pinblock 采用银联标准生成 pin^accNo *3:使用C加密pinblock得到最终的密码 * @author yangw@eastcom.com * */ public class NewThreeDes { static { Security.addProvider(new com.sun.crypto.provider.SunJCE()); } public static final String HTMK="C4F6E5A15B356D435BBC61E2ACFF6A42"; //A public static final String HPIN="5B35E077D48BF7E308219B550E6DD1FE"; //B /** * 3DES加密 * @param password 明文 * @param secretKey 密钥 * @return 16进制形式的字符串 * @throws Exception */ public static String encrypt(byte[] password,byte[] secretKey) throws Exception { SecretKeySpec key = new SecretKeySpec(secretKey, "DESede"); Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding"); // TripleDES/ECB/NoPadding cipher.init(Cipher.ENCRYPT_MODE, key); byte[] cipherText = cipher.doFinal(password); return byte2HexStr(cipherText); } /** * 3DES解密 * @param password 密文 * @return byte[]形式的明文 * @throws Exception */ public static byte[] decrypt(String password,byte[] keyBytes) throws Exception { byte[] input = hexStr2Bytes(password); SecretKeySpec key = new SecretKeySpec(keyBytes, "DESede"); Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(input); } /** * 十六进制转成二进制 * @param src * @return */ public static byte[] hexStr2Bytes(String src) { int m = 0, n = 0; int l = src.length() / 2; byte[] ret = new byte[l]; for (int i = 0; i < l; i++) { m = i * 2 + 1; n = m + 1; ret[i] = uniteBytes(src.substring(i * 2, m), src.substring(m, n)); } return ret; } private static byte uniteBytes(String src0, String src1) { byte b0 = Byte.decode("0x" + src0).byteValue(); b0 = (byte) (b0 << 4); byte b1 = Byte.decode("0x" + src1).byteValue(); byte ret = (byte) (b0 | b1); return ret; } /** * * 十六进制字符串转换成byte[] * @param hexStr 待转换的字符串 * @param length hexStr必须达到的长度 * @param isLeft 左边补还是右边补 * @param hexStr 填充的字符 */ public static byte[] hexStr2Str(String hexStr) { // 因为3DES是对称加密算法,key是24位,当只有16位时,后8位取key的前8位 StringBuffer sb=new StringBuffer(hexStr); sb.append(hexStr.substring(0,16));//字符串是16位, 就是8位byte hexStr=sb.toString(); // 转换的过程 String str = "0123456789ABCDEF"; char[] hexs = hexStr.toCharArray(); byte[] bytes = new byte[hexStr.length() / 2]; int n; for (int i = 0; i < bytes.length; i++) { n = str.indexOf(hexs[2 * i]) * 16; n += str.indexOf(hexs[2 * i + 1]); bytes[i] = (byte) (n & 0xff); } return bytes; } /** * bytes转换成十六进制字符串 */ public static String byte2HexStr(byte[] b) { String hs = ""; String stmp = ""; for (int n = 0; n < b.length; n++) { stmp = (Integer.toHexString(b[n] & 0XFF)); if (stmp.length() == 1) hs = hs + "0" + stmp; else hs = hs + stmp; } return hs.toUpperCase(); } /** * * @param src0 * @param src1 * @return */ private static byte uniteBytes(byte src0, byte src1) { byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 })).byteValue(); _b0 = (byte) (_b0 << 4); byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 })).byteValue(); byte ret = (byte) (_b0 ^ _b1); return ret; } /** * 对pin进行加密 * @param pin * @return */ private static byte[] getHPin(String pin) { byte arrPin[] = pin.getBytes(); byte encode[] = new byte[8]; encode[0] = (byte) 0x06; encode[1] = (byte) uniteBytes(arrPin[0], arrPin[1]); encode[2] = (byte) uniteBytes(arrPin[2], arrPin[3]); encode[3] = (byte) uniteBytes(arrPin[4], arrPin[5]); encode[4] = (byte) 0xFF; encode[5] = (byte) 0xFF; encode[6] = (byte) 0xFF; encode[7] = (byte) 0xFF; return encode; } /** * PIN加密的主帐号 * @param accno * @return */ private static byte[] getHAccno(String accno) { int len = accno.length(); byte arrTemp[] = accno.substring(len < 13 ? 0 : len - 13, len - 1).getBytes(); byte arrAccno[] = new byte[12]; for (int i = 0; i < 12; i++) { arrAccno[i] = (i <= arrTemp.length ? arrTemp[i] : (byte) 0x00); } byte encode[] = new byte[8]; encode[0] = (byte) 0x00; encode[1] = (byte) 0x00; encode[2] = (byte) uniteBytes(arrAccno[0], arrAccno[1]); encode[3] = (byte) uniteBytes(arrAccno[2], arrAccno[3]); encode[4] = (byte) uniteBytes(arrAccno[4], arrAccno[5]); encode[5] = (byte) uniteBytes(arrAccno[6], arrAccno[7]); encode[6] = (byte) uniteBytes(arrAccno[8], arrAccno[9]); encode[7] = (byte) uniteBytes(arrAccno[10], arrAccno[11]); return encode; } /** * PIN BLOCK (PIN按位异或主帐号PAN) * @param pin 密码 * @param accno 账号 * /** * ANSI X9.8 Format(带主帐号信息) * PIN BLOCK 格式:等于 PIN 按位异或主帐号 PIN 格式:(与1中的格式类似) Byte 1 PIN的长度 Byte 2 – Byte 3/4/5/6/7 4--12个PIN(每个PIN占4个BIT) Byte4/5/6/7/8 – Byte 8 FILLER “F” (每个“F“占4个BIT) PAN(主帐号 Primary Account Number)同样包含8个byte,格式如下: Byte 1 — Byte 2 0x00 0x00 Byte 3 — Byte 8 12个主帐号字符(最后一位为校验位) 12位字符主帐号的取法:取主帐号的右12位(不包括最右边的校验位),不足12位左补“0X00”。 * @author yangw@eastcom.com * @return * */ public static byte[] process(String pin, String accno) { byte arrPin[] = getHPin(pin); byte arrAccno[] = getHAccno(accno); byte arrRet[] = new byte[8]; //PIN BLOCK 格式等于 PIN 按位异或 主帐号; for (int i = 0; i < 8; i++) { arrRet[i] = (byte) (arrPin[i] ^ arrAccno[i]); } return arrRet; } /** * 初始化密钥 */ public static byte[] initSecretKey() throws Exception{ byte[] init= hexStr2Str(HTMK); //将字符串转成16进制的byte[]数组 return decrypt(HPIN,init); //用 HTMK解密HPIN } /** * 对账号和密码进行加密,生成加密后的密码 * @param accNo 账号或者卡号 * @param passwd 密码 * @return * @throws Exception */ public static String generatePasswd(String accNo,String passwd) throws Exception{ byte[] secretKeyBytes=initSecretKey(); //得到密钥 byte[] pinblock = process(passwd,accNo); System.out.println(secretKeyBytes.length); // 因为3DES是对称加密算法,key是24位,当只有16位时,后8位取key的前8位 byte[] temp = new byte[24]; System.arraycopy(secretKeyBytes, 0, temp, 0, secretKeyBytes.length); System.arraycopy(secretKeyBytes, 0, temp, secretKeyBytes.length, 8); return encrypt(pinblock,temp); } // // public static void printHexString(String hint, byte[] b) { // System.out.print(hint); // for (int i = 0; i < b.length; i++) { // String hex = Integer.toHexString(b[i] & 0xFF); // if (hex.length() == 1) { // hex = '0' + hex; // } // System.out.print(hex.toUpperCase() + " "); // } // System.out.println(""); // } // public static void main(String[] args) { // try { // // 81098C8B11986FD4 // System.out.println(generatePasswd("6228480478316226677","000000")); // // } catch (Exception e) { // e.printStackTrace(); // } // } // // // }
Java实现3DES加密--及ANSI X9.8 Format标准 PIN PAN获取PIN BlOCK的更多相关文章
- ANSI X9.8标准 PIN xor PAN获取PIN BlOCK
ANSI X9.8标准 PIN xor PAN获取PIN BlOCK 之前看到几篇介绍,把ANSI说成16个字节,真心扯淡,各种误人子弟,真正的ANSI算法其实是8个字节,具体格式如下: (1) AN ...
- Java中3DES加密解密与其他语言(如C/C++)通信
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- 如何用Java进行3DES加密解
原文地址: http://weavesky.com/2008/01/05/java-3des/ 最近一个合作商提出使用3DES交换数据,本来他们有现成的代码,可惜只有.net版本,我们的服务器都是Li ...
- c#加密,java解密(3DES加密)
c#代码 using System; using System.Security; using System.Security.Cryptography; using System.IO; using ...
- 【推荐】JAVA基础◆浅谈3DES加密解密
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- 3DES加密
本文介绍了3DES加密特性,加密特点,3DES是对称加密,用一个密钥对内容进行加密,必须使用相同的密钥进行解密, 密钥必须配置,而且长度为24位,不足24位,用0位进行补全,本文也顺带介绍了其它加密算 ...
- C# 3Des加密解密
第三方的加密规则约定:加密经过3DES加密后的Base64 编码 最近在对接一个第三方接口,请求参数和响应参数全采用3des加密规则,由于我是用.NET对接的,而第三方是Java开发的,所以两种程 ...
- JAVA和C# 3DES加密解密
最近 一个项目.net 要调用JAVA的WEB SERVICE,数据采用3DES加密,涉及到两种语言3DES一致性的问题, 下面分享一下, 这里的KEY采用Base64编码,便用分发,因为Java的B ...
- C# Java 3DES加密解密 扩展及修正\0 问题
注: C#已亲测及做扩展, Java 部分未做验证 /// <summary> /// 3DES加密解密 /// ------------------------------------- ...
随机推荐
- 【3D数学基础】三维空间折射向量计算
问题:在三维空间中,已知折射率 e .入射角 L 和法线 N. 要求:计算出折射向量 T. 其中: L. N 和 T 都为单位向量. 如图片所示,下面所有的公式都看着这张图片来求解的: 首先,我们必须 ...
- CentOS自带mysql配置(密码更改、端口开放访问、添加进系统启动项)
前些天虚拟机安装好了CentOS6.1,但是自己想远程连接自带的mysql发现不知道如何改密码,于是谷歌一下,把结果记录下来,方便后期自己使用: 方法一: # /etc/init.d/mysql st ...
- 通过 PHP 连接China Azure Blob 存储
问题说明 Azure Blob 存储是一种将非结构化数据作为对象/Blob存储在云中的服务.Blob存储可以存储任何类型的文本或二进制数据,例如文档.媒体文件或应用程序安装程序.Blob存储也称为对象 ...
- 渗透常用手工SQL注入语句合集
1.判断有无注入点; and 1=1 and 1=2 2.猜表一般的表的名称无非是admin adminuser user pass password 等..and 0<>(select ...
- C#使用Xamarin开发可移植移动应用进阶篇(9.混淆代码,防止反编译)
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 今天讲讲如 ...
- 7-zip 解压
7-zip 解压 1.引入依赖文件 sevenzipjbinding.jar sevenzipjbinding-Allwindows.jar <!-- https://mvnrepository ...
- 【搬运工】之YSlow安装教程
YSlow安装教程(我只是搬运工,推荐好用的地址) 地址: https://devework.com/yslow.html YSlow (解析为 why slow)是雅虎基于网站优化规则推出的工具,帮 ...
- Akka(23): Stream:自定义流构件功能-Custom defined stream processing stages
从总体上看:akka-stream是由数据源头Source,流通节点Flow和数据流终点Sink三个框架性的流构件(stream components)组成的.这其中:Source和Sink是stre ...
- .Net Mvc实现各种表格随意切换插件
一套Js代码,.只要改参数 在3种表格之间任意切换-(使用Js面向对象封装,可重写方法) 任意表格皮肤随便切换 flextgrid/bootstrapt/jqgrid 1 001 @{ 002 ...
- Zookeeper的安装的配置
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt192 安装和配置详解 本文介绍的 Zookeeper 是以 3.2.2 这个 ...