PIN加密有3个要素,PIN-KEY,PIN,PAN。
PIN-KEY也就是加密的密钥,这里采用的3DES加密,所以PIN-KEY长度要么是16个字节要么是24个字节,也即是要么采用128位长密钥要么采用192长字节;PIN也就是要加密的明文,这里可能是账户密码,也可能是登录密码的明文;使用PIN加密,在加密之前,首先使用一串数字和PIN异或,然后将异或后的数据拿来进行3DES加密,这样加密出来的数据就是PIN加密结果。通常每次加密时采用的PAN不一样。当时解密的时候也需要取得该PAN进行解密。使用策略模式以方便以后扩展其他加密算法。对接口不满足的可适当通过Adapter调整
实现示例:
/**
*@(#)EncryRule.java1.02007-10-23
*/
package com.security;
/**
* 数据加密Strategy
*
* @author tsimgsong
* @version 1.0,2007-10-15
*
*/
public abstract class EncryRule {
/**
* 明文
*/
protected String plainText = "";
/**
* 密文
*/
protected String encryedText = "";
/**
* 取密文
* @return String 密文
*/
public String getEncryedText(){
return encryedText;
}
/**
* 设置密文
* @param encryedText 密文
*/
public void setEncryedText(String encryedText) {
this.encryedText = encryedText;
}
/**
* 取明文
* @return String 明文
*/
public String getPlainText(){
return plainText;
}
/**
* 设置明文
* @param plainText 明文
*/
public void setPlainText(String plainText){
this.plainText = plainText;
}
/**
* 加密操作
*
*/
public abstract void encry();
/**
* 解密操作
*
*/
public abstract void deEncry();
}
/**
*@(#)PinEncry.java1.02007-10-23
*/
package com.security;
import java.lang.reflect.Array;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
/**
* PIN码加密,加密报文通信中需要传输的客户密码
* <br>
*
* @author tsimgsong
* @version 1.0,2007-10-15
*
*/
public class PinEncry extends EncryRule {
private static boolean initialized = false;
// 密钥24个字节,192位
private static String key_pin ;
// pin和pan的长度,值域长度为30,前面2位长度表示值域的长度
private static final int LENGTH_PIN = 32;
private static final int LENGTH_PAN = 32;
private static final int LENGTH_PWD = 0;
// 加密3DES变量
private static Cipher cipher = null;
// 解密3DES变量
private static Cipher deCipher = null;
// 加密算法
private static final String ALGORITHM = "DESede";
private static SecretKey key = null;
/**
* "00"+网银流水号+交易日期+客户号+操作员编号
* <br> 前面两位为数据长度,设为定值00,数据30位长,不足左补0,超过30位保留后30个字节
*/
private String pan = "";
static {
if (!initialized) {
pinEncryInit();
initialized = true;
}
}
/**
*初始化加密要素,从数据库中提取PIN密码
*
*/
private static void pinEncryInit() {
System.out.println("Pin Encry Parameters Initialize complete:success");
}
/**
* 重置加密密钥,从下次使用该功能时生效
*
*/
private static void reset() {
initialized = false;
System.out.println("Reset Pin Encry Parameters");
pinEncryInit();
}
/**
* PIN码加密
* <br>对明文进行3DES加密,没8个字节处理一次,对第一个8字节进行3DES加密,后面每8个字节都和前面的加密结果进行异或后3DES加密</br>
*
*/
public void encry() {
encryedText = plainText;
// PIN nor PAN
byte[] toBeEncry = null;
toBeEncry = norProcess(plainText, pan);
// System.out.println("Before 3DES:"+encryedText +"Base64:"+new sun.misc.BASE64Encoder().encode(encryedText.getBytes()));
try {
// 明文
// 密文 存放计算后的数据
byte[] encryedData = new byte[toBeEncry.length];
// 本次需要进行处理的数据 一次最多处理8个字节
byte[] encrying = new byte[8];
// 3DeS需要以字节数组的方式进行加密
} catch (Exception e) {
e.printStackTrace();
}
}
public void deEncry(){
byte[] deEncryed = null;
try {
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(encryedText);
byte[] mDec = new byte[8];
deEncryed = new byte[dec.length];
System.arraycopy(dec,0,deEncryed,0,dec.length);
}
encryedText = new sun.misc.BASE64Encoder().encode(deEncryed);
// System.out.println("After De3DES :"+encryedText);
} catch (Exception e) {
e.printStackTrace();
}
plainText = denorProcess(deEncryed,pan);
}
/**
* 数据异或处理<br>
*
* @param pin 密码长度(2Byte)+客户密码<br> 密钥最长不超过30位,不足部分右补0
* @param pan "00"+网银流水号+交易日期+客户号+操作员编号
* <br> 前面两位为数据长度,设为定值00,数据30位长,不足左补0,超过30位保留后30个字节
* @return PIN String Block
*/
private byte[] norProcess(String pin,String pan){
// 异或结果存放
int[] norNum=new int[LENGTH_PIN];
byte[] norRes = new byte[LENGTH_PIN];
byte bb;
String temp = "";
String result="";
// System.out.println("PIN:"+pin);
// System.out.println("PAN:"+pan);
// 密码不足30位右补0
for(int i = pin.length() ;i <LENGTH_PIN ;i++){
pin = pin+"0";
}
// pan不足30位左补0
for(int i = pan.length() ;i<LENGTH_PAN ;i++){
pan = "0"+pan;
}
// pan超过30位去后30位
if(pan.length() > LENGTH_PAN){
pan = pan.substring(pan.length()-LENGTH_PAN,pan.length());
}
for(int i=0;i<LENGTH_PIN;i++){
norRes[i] =(byte) (pin.charAt(i)^pan.charAt(i));
}
// System.out.print("Nor Result:");
// for(int i = 0 ;i<norRes.length ;i++){
// System.out.print(Integer.toHexString(norRes[i])+" ");
// }
// System.out.println();
return norRes;//new String(norRes);
}
/**
* 异或结果还原处理
*
* @param norStr 异或值
* @param pan "00"+交易日期+交易时间+客户号+操作员编号
* <br> 前面两位为数据长度,设为定值00,数据30位长,不足左补0,超过30位保留后30个字节
* @return String 异或原串
*/
private String denorProcess(byte[] norStr,String pan){
byte[] snNum=norStr;
String result="";
// pan不足30位左补0
for(int i = pan.length() ;i<LENGTH_PAN ;i++){
pan = "0"+pan;
}
// pan超过30位去后30位
if (pan.length() > LENGTH_PAN) {
pan = pan.substring(pan.length() - LENGTH_PAN, pan.length());
}
int n = 0;
for(int i=0;i<norStr.length;i++){
snNum[i]=(byte)(norStr[i]^pan.charAt(i));
}
for(int k=0;k< norStr.length;k++){
result+=(char)snNum[k];
}
// System.out.println("DeNcry result:"+result);
return result;
}
/**
* 取Pan值
* @return String
*/
public String getPan() {
return pan;
}
/**
* 设置Pan值
* @param pan
*/
public void setPan(String pan) {
this.pan = pan;
}
}
/**
*@(#)PinEncry.java1.02007-10-23
*/
Package com.security;
/**
* 数据加密策略
*
* @author tsimgsong
* @version 1.0,2007-10-15
*
*/
public class EncrySolve {
// 加密策略
static EncryRule rule ;
/**
* 加密运算
* @param r 加密策略
* @param plainText 明文
* @return String 加密后数据
*/
public static String encry(EncryRule r,String plainText){
rule = r;
rule.setPlainText(plainText);
rule.encry();
return rule.getEncryedText();
}
/**
* 解密运算
* @param r 解密策略
* @param encryedText 密文
* @return String 明文
*/
public static String deEncry(EncryRule r,String encryedText){
rule = r;
rule.setEncryedText(encryedText);
rule.deEncry();
return rule.getPlainText();
}
/**
* 取密文
* @return
*/
public String getEncryedText(){
return rule.getEncryedText();
}
/**
* 取明文
* @return
*/
public String getPlainText(){
return rule.getPlainText();
}
}
Junit测试:
PinEncry pe = new PinEncry();
String passwd = "000001";
int length_passwd = passwd.length() ;
if(length_passwd<10){
passwd = "0"+length_passwd+passwd;
}else{
passwd = ""+length_passwd+passwd;
}
PinEncry pe = new PinEncry();
// 组织Pan值 交易日期YYYYMMDD+企业客户号+操作员编号
String pan = "00";
pan = "383090020071022799070001";
pe.setPan(pan);
加密:
passwd = (EncrySolve.encry(pe,passwd));
assertEquals(‘X065VL+nZV6/jP8XjJq6FmMH18egeDW852gA2RzTF0Q=’,passwd);
解密:
passwd=EncrySolve.deEncry(pe,"X065VL+nZV6/jP8XjJq6FmMH18egeDW852gA2RzTF0Q=");
loger.debug(passwd);
密码进行加密之前必须计算出密码原文的长度,并以两个字节的长度放置在明文的前面,后面根据密码的长度进行截取。加密后的数据进行了Base64编码。
3DES算法就是进行了3次DES计算,用第一个密钥进行一次加密,用第二个密钥进行一次解密,之后再用第3个密钥进行一次加密,DES加密的密钥长度是64位,如果采用192位密码加密,那个三个密钥分别取依次的64位,如果采用128位密钥,第一个和第三个的密钥相同
银行PIN数据加密
最新推荐文章于 2023-07-10 18:45:27 发布