定义枚举类型,包含已经集成的加密算法
package com.sunld.manager_core.tools.encipher.enums;
/** * @author 孙辽东
* <p>createDate:2014年3月7日 上午11:30:44</p>
* @version V1.0
*/
public enum EncipherEnum {
BASE64,
MD5,
SHA,
HMAC,
DES
}
设计工厂模式,定义了加密和解密抽象方法,并且使用反射实例化具体的Factory
package com.sunld.manager_core.tools.encipher.factory;
import com.sunld.manager_core.exception.BusinessException;
import com.sunld.manager_core.factory.FactoryInterface;
import com.sunld.manager_core.file.property.PropertyUtil;
import com.sunld.manager_core.tools.encipher.enums.EncipherEnum;
import com.sunld.manager_core.util.rtti.ClassUtils;
/** * <p>加密工厂类</p>
* @author 孙辽东
* <p>createDate:2014年3月7日 上午11:27:08</p>
* @version V1.0
*/
public abstract class EncipherFactory implements FactoryInterface{
protected static final String ENCIPHERKEY = PropertyUtil.getPropertyValue("SYSTEM.ENCIPHERKEY");
/**
* <p>Protected constructor to prevent instantiation.
* Use {@link #newInstance}</p>
* <p>createDate:2014年3月7日 上午11:29:35</p>
*/
protected EncipherFactory(){}
/** *
* @param encipherEnum {@link EncipherEnum}
* @return EncipherFactory
* <p>createDate:2014年3月7日 上午11:30:59</p>
*/
public static EncipherFactory newInstance(EncipherEnum encipherEnum){
try {
return (EncipherFactory) ClassUtils.forName(PropertyUtil.getPropertyValue("SYSTEM."+encipherEnum)).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new BusinessException("很抱歉,名称为"+encipherEnum+"的获取加密算法的具体工厂还没创建!",e);
}
}
public abstract String encrypt(String str);
public abstract String decrypt(String str);
}
具体实现
BASE64Encipher
package com.sunld.manager_core.tools.encipher.encipherstrategy;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import com.sunld.manager_core.exception.BusinessException;
import com.sunld.manager_core.exception.ExceptionUtil;
import com.sunld.manager_core.tools.encipher.factory.EncipherFactory;
import com.sunld.manager_core.util.other.StringUtil;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* <p>BASE64的加密解密是双向的,可以求反解。</p>
* @author 孙辽东
* <p>createDate:2014年3月7日 上午11:40:59</p>
* @version V1.0
*/
public class BASE64Encipher extends EncipherFactory{
public String encrypt(String str) {
if(StringUtil.isNotNull(str)){
byte[] b = null;
try {
b = (str+ENCIPHERKEY).getBytes("utf-8");//防止中文乱码utf-8,并且转换成对应的编码
} catch (UnsupportedEncodingException e) {
throw new BusinessException("采用BASE64算法加密失败:"+ExceptionUtil.formatException(e),e);
}
return (new BASE64Encoder()).encodeBuffer(b);
}else{
return "";
}
}
public String decrypt(String str) {
if(StringUtil.isNotNull(str)){
String result = "";
try {
byte[] b = (new BASE64Decoder()).decodeBuffer(str);
result = new String(b,"utf-8");
result = result.substring(0,result.indexOf(ENCIPHERKEY));
} catch (IOException e) {
throw new BusinessException("采用BASE64算法解密失败:"+ExceptionUtil.formatException(e),e);
}
return result;
}else{
return "";
}
}
}
DESPlusEncipher
package com.sunld.manager_core.tools.encipher.encipherstrategy;
import java.security.Key;
import java.security.Security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import com.sunld.manager_core.exception.BusinessException;
import com.sunld.manager_core.exception.ExceptionUtil;
import com.sunld.manager_core.tools.encipher.factory.EncipherFactory;
import com.sunld.manager_core.util.other.StringUtil;
/**
* <p>DES DES-Data Encryption Standard,即数据加密算法。DES算法的入口参数有三个:Key、Data、Mode。</p>
* <p>Key:8个字节共64位,是DES算法的工作密钥;</p>
* <p>Data:8个字节64位,是要被加密或被解密的数据;</p>
* <p>Mode:DES的工作方式,有两种:加密或解密。</p>
* @author 孙辽东
* <p>createDate:2014年3月7日 下午1:35:34</p>
* @version V1.0
*/
public class DESPlusEncipher extends EncipherFactory{
private Cipher encryptCipher = null;
private Cipher decryptCipher = null;
/** * 完成信息初始化 * <p>createDate:2014年3月7日 下午1:57:34</p> */
public DESPlusEncipher(){
Security.addProvider(new com.sun.crypto.provider.SunJCE());
Key key = getKey(ENCIPHERKEY.getBytes());
try{
encryptCipher = Cipher.getInstance("DES");
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
decryptCipher = Cipher.getInstance("DES");
decryptCipher.init(Cipher.DECRYPT_MODE, key);
}catch(Exception e){
throw new BusinessException("构造DES加密器时出错!",e);
}
}
public String encrypt(String str) {
try {
return StringUtil.byteArray2HexStr(encryptCipher.doFinal(str.getBytes()));
} catch (IllegalBlockSizeException | BadPaddingException e) {
throw new BusinessException("采用DES算法加密失败:"+ExceptionUtil.formatException(e),e);
}
}
public String decrypt(String str) {
try {
return new String(decryptCipher.doFinal(StringUtil.hexStr2ByteArray(str)));
} catch (IllegalBlockSizeException | BadPaddingException e) {
throw new BusinessException("采用DES算法解密失败:"+ExceptionUtil.formatException(e),e);
}
}
/**
* <p>从指定字符串生成密钥,密钥所需的字节数组长度为8位 不足8位时后面补0,超出8位只取前8位</p>
* @param arrBTmp
* @return Key
* <p>createDate:2014年3月7日 下午1:59:01</p>
*/
private Key getKey(byte[] arrBTmp){
// 创建一个空的8位字节数组(默认值为0)
byte[] arrB = new byte[8];
// 将原始字节数组转换为8位
for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
arrB[i] = arrBTmp[i];
}
// 生成密钥
Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
return key;
}
}
HMACEncipher
package com.sunld.manager_core.tools.encipher.encipherstrategy;
import java.math.BigInteger;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import com.sunld.manager_core.exception.BusinessException;
import com.sunld.manager_core.exception.ExceptionUtil;
import com.sunld.manager_core.tools.encipher.factory.EncipherFactory;
import com.sunld.manager_core.util.other.StringUtil;
/**
* <p>HMAC是单向加密,任何数据加密后只会产生唯一的一个加密串,通常用来校验数据在传输过程中是否被修改。</p>
* <p>HMAC算法有一个密钥,增强了数据传输过程中的安全性,强化了算法外的不可控因素。</p>
* @author 孙辽东
* <p>createDate:2014年3月7日 下午1:21:57</p>
* @version V1.0
*/
public class HMACEncipher extends EncipherFactory{
private static final String MACKEY = "HmacMD5";
public String encrypt(String str) {
if(StringUtil.isNotNull(str)){
String result = "";
try{
SecretKey secretKey = new SecretKeySpec(ENCIPHERKEY.getBytes(), MACKEY);
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
byte[] b = mac.doFinal((str+ENCIPHERKEY).getBytes());
result = (new BigInteger(b)).toString(16);
}catch(Exception e){
throw new BusinessException("采用HMAC算法加密失败:"+ExceptionUtil.formatException(e),e);
}
return result;
}else{
return "";
}
}
public String decrypt(String str) {
throw new BusinessException("HMAC加密算法是单项的,不能进行反向解密");
}
/**
* 签名工具
* @return String
* <p>createDate:2014年3月7日 下午1:25:53</p>
*/
public String initMacKey(){
String key = "";
try{
KeyGenerator keyGenerator = KeyGenerator.getInstance(MACKEY);
SecretKey secretKey = keyGenerator.generateKey();
byte[] b = secretKey.getEncoded();
String str = new String(b);
key = str;
}catch(Exception e){
throw new BusinessException("在使用HMAC加密算法获取密钥时出错:"+ExceptionUtil.formatException(e),e);
}
return key;
}
}
MD5Encipher
package com.sunld.manager_core.tools.encipher.encipherstrategy;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.sunld.manager_core.exception.BusinessException;
import com.sunld.manager_core.exception.ExceptionUtil;
import com.sunld.manager_core.tools.encipher.factory.EncipherFactory;
import com.sunld.manager_core.util.other.StringUtil;
/**
* <p>MD5是单向加密,任何数据加密后只会产生唯一的一个加密串,通常用来校验数据在传输过程中是否被修改。</p>
* @author 孙辽东
* <p>createDate:2014年3月7日 下午1:05:16</p>
* @version V1.0
*/
public class MD5Encipher extends EncipherFactory{
public String encrypt(String str) {
if(StringUtil.isNotNull(str)){
String result = "";
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
md.update((str+ENCIPHERKEY).getBytes());
byte[] b = md.digest();
result = StringUtil.byteArray2HexStr(b);
} catch (NoSuchAlgorithmException e) {
throw new BusinessException("采用MD5算法加密失败:"+ExceptionUtil.formatException(e),e);
}
return result;
}else{
return "";
}
}
public String decrypt(String str) {
throw new BusinessException("MD5加密算法是单项的,不能进行反向解密");
}
}
SHAEncipher
package com.sunld.manager_core.tools.encipher.encipherstrategy;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.sunld.manager_core.exception.BusinessException;
import com.sunld.manager_core.exception.ExceptionUtil;
import com.sunld.manager_core.tools.encipher.factory.EncipherFactory;
import com.sunld.manager_core.util.other.StringUtil;
/**
* <p>SHA是单向加密,任何数据加密后只会产生唯一的一个加密串,通常用来校验数据在传输过程中是否被修改。</p>
* @author 孙辽东
* <p>createDate:2014年3月7日 下午1:18:48</p>
* @version V1.0
*/
public class SHAEncipher extends EncipherFactory{
public String encrypt(String str) {
if(StringUtil.isNotNull(str)){
String result = "";
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA");
md.update((str+ENCIPHERKEY).getBytes());
byte[] b = md.digest();
result = StringUtil.byteArray2HexStr(b);
} catch (NoSuchAlgorithmException e) {
throw new BusinessException("采用SHA算法加密失败:"+ExceptionUtil.formatException(e),e);
}
return result;
}else{
return "";
}
}
public String decrypt(String str) {
throw new BusinessException("SHA加密算法是单项的,不能进行反向解密");
}
}
根据不同的加密算法生成相关的key
KeyStrategy
package com.sunld.manager_core.tools.encipher.keystrategy;
import com.sunld.manager_core.factory.LogDefinitionFactory;
/**
* @author 孙辽东
* <p>createDate:2014年5月29日 上午11:37:18</p>
* @version V1.0
*/
public interface KeyStrategy extends LogDefinitionFactory{
public abstract String toKey(String paramString, Object paramObject);
}
AbstractKeyStrategy
package com.sunld.manager_core.tools.encipher.keystrategy;
import java.util.regex.Pattern;
import com.sunld.manager_core.tools.encipher.enums.EncipherEnum;
import com.sunld.manager_core.tools.encipher.factory.EncipherFactory;
/**
* @author 孙辽东
* <p>createDate:2014年5月29日 上午11:41:04</p>
* @version V1.0
*/
public abstract class AbstractKeyStrategy implements KeyStrategy{
private static final int DEFAULT_MAX_KEY_LENGTH = 250;
private static final Pattern CLEAN_PATTERN = Pattern.compile("\\s");
private int maxKeyLength;
public AbstractKeyStrategy(){
this.maxKeyLength = DEFAULT_MAX_KEY_LENGTH;
}
public String toKey(String regionName, Object key) {
if (key == null) {
throw new IllegalArgumentException("key must not be null");
}
String keyString = concatenateKey(regionName, transformKeyObject(key));
if (keyString.length() > this.maxKeyLength) {
return truncateKey(keyString);
}
String finalKey = CLEAN_PATTERN.matcher(keyString).replaceAll("");
LOGGER.debug("Final cache key: [{" + finalKey + "}]");
return finalKey;
}
protected abstract String transformKeyObject(Object paramObject);
protected String truncateKey(String key){
String keyHashCode = EncipherFactory.newInstance(EncipherEnum.MD5).encrypt(key);
LOGGER.warn("Encoded key [{" + key + "}] to md5 hash [{" + keyHashCode + "}]. " + "Be sure to set cache region names whenever possible as the names Hibernate generates are really long.");
return keyHashCode;
}
public int getMaxKeyLength() {
return this.maxKeyLength;
}
public void setMaxKeyLength(int maxKeyLength) {
this.maxKeyLength = maxKeyLength;
}
protected String concatenateKey(String regionName, Object key) {
return regionName + ":" + String.valueOf(key);
}
}
HashCodeKeyStrategy
package com.sunld.manager_core.tools.encipher.keystrategy;
/**
* @author 孙辽东
* <p>createDate:2014年5月29日 上午11:40:28</p>
* @version V1.0
*/
public class HashCodeKeyStrategy extends AbstractKeyStrategy{
protected String transformKeyObject(Object key){
int hashCode = key.hashCode();
if (LOGGER.isInfoEnabled())
LOGGER.info("Transformed key [{" + key + "}] to hashCode [{" + hashCode + "}]");
return String.valueOf(hashCode);
}
}
Md5KeyStrategy
package com.sunld.manager_core.tools.encipher.keystrategy;
import com.sunld.manager_core.tools.encipher.enums.EncipherEnum;
import com.sunld.manager_core.tools.encipher.factory.EncipherFactory;
/**
* @author 孙辽东
* <p>createDate:2014年5月29日 上午11:49:13</p>
* @version V1.0
*/
public class Md5KeyStrategy extends HashCodeKeyStrategy{
protected String concatenateKey(String regionName, Object key){
String longKey = super.concatenateKey(regionName, key);
return EncipherFactory.newInstance(EncipherEnum.MD5).encrypt(longKey);
}
}
Sha1KeyStrategy
package com.sunld.manager_core.tools.encipher.keystrategy;
import com.sunld.manager_core.tools.encipher.enums.EncipherEnum;
import com.sunld.manager_core.tools.encipher.factory.EncipherFactory;
/**
* @author 孙辽东
* <p>createDate:2014年5月29日 上午11:51:22</p>
* @version V1.0
*/
public class Sha1KeyStrategy extends HashCodeKeyStrategy{
protected String concatenateKey(String regionName, Object key){
String longKey = super.concatenateKey(regionName, key);
return EncipherFactory.newInstance(EncipherEnum.SHA).encrypt(longKey);
}
}
StringKeyStrategy
package com.sunld.manager_core.tools.encipher.keystrategy;
/**
* @author 孙辽东
* <p>createDate:2014年5月29日 上午11:52:38</p>
* @version V1.0
*/
public class StringKeyStrategy extends AbstractKeyStrategy{
protected String transformKeyObject(Object key){
String stringKey = String.valueOf(key);
if (LOGGER.isInfoEnabled())
LOGGER.info("Transformed key [{" + key + "}] to string [{" + stringKey + "}]");
return stringKey;
}
}