使用工厂模式、策略模式实现BASE64,MD5,SHA,HMAC,DES各种加密算法

36 篇文章 2 订阅
20 篇文章 1 订阅

定义枚举类型,包含已经集成的加密算法

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;
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值