加密算法

import java.security.SecureRandom;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class YFSDEncode {

	public static void main(String[] args) {
		//System.out.println(isHex16("********************************"));
		String pan="6058280000000001";
		String pin="12345678";
		String key="*********************************";
//		String panEncode="0000"+pan.substring(pan.length()-13, pan.length()-1);
//		String pin1="0"+pin.length()+pin;
//		String pinEncode=String.format("%-16s", pin1).replaceAll(" ", "F");//用F补足16位
//		String panAndPinYihuo=hxor(panEncode,pinEncode);
//		//System.out.println(panAndPinYihuo);
//		byte[] en3DES = encECB3Des(hex2byte(key), hexStr2Str(panAndPinYihuo));
//		System.out.println(byte2HexStr(en3DES,16).substring(0, 16));
		System.out.println(encode(pan,pin,key));
	}
	
	private final static char[] mChars = "0123456789ABCDEF".toCharArray();
	
	/**
	 * 加密入口
	 * @param pan 卡号:必须是16到19位的数字
	 * @param pin 卡密码:必须是6到8位的数字
	 * @param key 3des加密密钥:必须是32位的0-9 a-f A-F 字符串
	 * @return 密钥
	 */
	public static String encode(String pan,String pin,String key){
		String outPutStr="";
		if(!checkInputParams(pan,pin,key)){
			return "输入参数有误:卡号必须是16到19位的数字,卡密码必须是6到8位的数字,加密密钥必须是32位的0-9 a-f A-F 字符串";
		}
		String panEncode="0000"+pan.substring(pan.length()-13, pan.length()-1);
		String pin1="0"+pin.length()+pin;
		String pinEncode=String.format("%-16s", pin1).replaceAll(" ", "F");//用F补足16位
		String panAndPinYihuo=hxor(panEncode,pinEncode);
		byte[] en3DES = encECB3Des(hex2byte(key), hexStr2Str(panAndPinYihuo));
		outPutStr=byte2HexStr(en3DES,16).substring(0, 16);
		return outPutStr;
	}
	

	/**
	 * 
	 * @param strHex_X
	 *            0-9 a-f的字符
	 * @param strHex_Y
	 *            0-9 a-f的字符
	 * @return 字符异或
	 */
	private static String xor(String strHex_X, String strHex_Y) {
		// 将x、y转成二进制形式
		String anotherBinary = Integer.toBinaryString(Integer.valueOf(strHex_X,
				16));
		String thisBinary = Integer.toBinaryString(Integer
				.valueOf(strHex_Y, 16));
		String result = "";
		// 判断是否为8位二进制,否则左补零
		if (anotherBinary.length() != 8) {
			for (int i = anotherBinary.length(); i < 8; i++) {
				anotherBinary = "0" + anotherBinary;
			}
		}
		if (thisBinary.length() != 8) {
			for (int i = thisBinary.length(); i < 8; i++) {
				thisBinary = "0" + thisBinary;
			}
		}
		// 异或运算
		for (int i = 0; i < anotherBinary.length(); i++) {
			// 如果相同位置数相同,则补0,否则补1
			if (thisBinary.charAt(i) == anotherBinary.charAt(i))
				result += "0";
			else {
				result += "1";
			}
		}
		return Integer.toHexString(Integer.parseInt(result, 2)).toUpperCase();
	}

	/**
	 * 
	 * @param strHex_X
	 *            0-9 a-f字符串
	 * @param strHex_Y
	 *            0-9 a-f字符串
	 * @return 字符串异或
	 */
	private static String hxor(String strHex_X, String strHex_Y) {
		String rt = "";
		if (strHex_X.length() == 16 && strHex_X.length() == strHex_Y.length()) {
			for (int i = 0; i < strHex_X.length(); i++) {
				rt = rt
						+ xor(strHex_X.substring(i, i + 1),
								strHex_Y.substring(i, i + 1));
			}
		}
		return rt;
	}

	/**
	 * 输入参数校验
	 * @param pan 卡号:必须是16到19位的数字
	 * @param pin 卡密码:必须是6到8位的数字
	 * @param key 3des加密密钥:必须是32位的0-9 a-f A-F 字符串
	 * @return
	 */
	private static boolean checkInputParams(String pan, String pin, String des3Key) {
		if (!StringUtils.isNoneBlank(pan, pin, des3Key)) {
			return false;
		}
		if (pan.length() < 16 || pan.length() > 19 || pin.length() < 6
				|| pin.length() > 8 || des3Key.length() != 32) {
			return false;
		}
		if (isNumeric(pan) && isNumeric(pin)&&isHex16(des3Key)) {
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 数字校验
	 * @param str
	 * @return
	 */
	public static boolean isNumeric(String str) {
		Pattern pattern = Pattern.compile("[0-9]*");
		Matcher isNum = pattern.matcher(str);
		if (!isNum.matches()) {
			return false;
		}
		return true;
	}
	
	/**
	 * A-F a-f 0-9 字符串校验
	 * @param str
	 * @return
	 */
	public static boolean isHex16(String str) {
		Pattern pattern = Pattern.compile("[A-F a-f 0-9]*");
		Matcher isNum = pattern.matcher(str);
		if (!isNum.matches()) {
			return false;
		}
		return true;
	}	
	
    /**
     * 将16进制字符串转换为byte[]
     * 
     * @param str
     * @return
     */
    public static byte[] hex2byte(String str) {
        if(str == null || str.trim().equals("")) {
            return new byte[0];
        }

        byte[] bytes = new byte[str.length() / 2];
        for(int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }

        return bytes;
    }
    
    /**
	 * 
	 * 十六进制字符串转换成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转换成十六进制字符串
	 * 
	 * @param b
	 *            byte[] byte数组
	 * @param iLen
	 *            int 取前N位处理 N=iLen
	 * @return String 每个Byte值之间空格分隔
	 */
	public static String byte2HexStr(byte[] b, int iLen) {
		StringBuilder sb = new StringBuilder();
		for (int n = 0; n < iLen; n++) {
			sb.append(mChars[(b[n] & 0xFF) >> 4]);
			sb.append(mChars[b[n] & 0x0F]);
		}
		return sb.toString().trim().toUpperCase(Locale.US);
	}

	/**
	 * 3DES双倍长加密
	 * 
	 * @author Joey
	 * @param key
	 * @param src
	 * @return
	 */
	public static byte[] encECB3Des(byte[] key, byte[] src) {
		byte[] temp = null;
		byte[] temp1 = null;
		temp1 = encryptDes(subByte(key, 0, 8), src);
		temp = decryptDes(subByte(key, 8, 8), temp1);
		temp1 = encryptDes(subByte(key, 0, 8), temp);
		return temp1;
	}
	
	private static byte[] subByte(byte[] keyData, int begin, int length) {
		byte[] key = new byte[length];
		for (int i = begin; i < begin + length; i++)
			key[i - begin] = keyData[i];
		return key;
	}
	/**
	 * DES加密
	 * 
	 */
	public static byte[] encryptDes(byte[] key, byte[] src) {
		try {
			// 创建一个DESKeySpec对象
			DESKeySpec desKey = new DESKeySpec(key);
			// 创建一个密匙工厂
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			// 将DESKeySpec对象转换成SecretKey对象
			SecretKey secretKey = keyFactory.generateSecret(desKey);
			// Cipher对象实际完成解密操作
			Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
			// 用密匙初始化Cipher对象
			cipher.init(Cipher.ENCRYPT_MODE, secretKey);
			// 现在,获取数据并加密
			// 正式执行加密操作
			return cipher.doFinal(src);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * DES解密
	 * 
	 * @param key
	 * @param src
	 * @return
	 */
	public static byte[] decryptDes(byte[] key, byte[] src) {
		try {
			// DES算法要求有一个可信任的随机数源
			SecureRandom random = new SecureRandom();
			// 创建一个DESKeySpec对象
			DESKeySpec desKey = new DESKeySpec(key);
			// 创建一个密匙工厂
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			// 将DESKeySpec对象转换成SecretKey对象
			SecretKey secretKey = keyFactory.generateSecret(desKey);
			// Cipher对象实际完成解密操作
			Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
			// 用密匙初始化Cipher对象
			cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
			// 现在,获取数据并加密
			// 正式执行加密操作
			return cipher.doFinal(src);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

*************************************卡密码加密方式**************************************
示例 1
例如:卡密码为: 	123456			   									6到8位	
假设: 卡号为:		6058280000000001  	去掉最后一位,往前取12位 		最少16号
截取下的PAN:	828000000000	
则用于PIN 加密的卡密码 为:	0000828000000000
PIN BLOCK 为:06123456FFFFFFFF
异或结果为:  0612B6D6FFFFFFFF
工作密钥为:  11111111111111111111111111111111							固定32位
用工作密钥对异或结果做3DES加密:0612B6D6FFFFFFFF
加密结果为: 2874F1E4D15750B7	


*************************************调用方法**************************************
	/**
	 * @param args
	 * @throws ParseException
	 */
	public static void main(String[] args) throws ParseException {
		String key="********************************";
		String pan="6058280000000001";
		String pin="123456";
		System.out.println(YFSDEncode.encode(pan,pin,key));
	}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值