文档章节

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

翰霖学院
 翰霖学院
发布于 2017/07/24 08:58
字数 1830
阅读 6
收藏 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;
    }
}

© 著作权归作者所有

共有 人打赏支持
翰霖学院
粉丝 0
博文 67
码字总数 45112
作品 0
济南
高级程序员
私信 提问
简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

转载:原地址http://www.cnblogs.com/zhangchenliang/p/3700820.html 简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别 结合简单示例和UML图,讲解工厂模式简单原理。 一、引子 话说...

法斗斗
2018/05/08
0
0
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
2018/06/24
0
0
设计模式15——Template Method设计模式

Template Method模板方法设计模式定义一个操作中算法的骨架,将具体步骤的执行延迟到子类中实现。Java中的抽象类就是使用了模板方法设计模式。模板方法设计模式结构如下: 以文档处理为例,T...

小米米儿小
2014/01/24
0
0
Javascript策略模式理解以及应用

最近一直在看Javascript设计模式,想通过写文章来增加自己对策略模式的理解,同时记录自己学习的经历。希望大家看完之后觉得有收获可以帮忙点个赞表示支持。 策略模式的定义 策略模式的定义是...

arzh
2018/12/18
0
0
Android 架构师9 设计模式之策略模式

前言 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们之间可以相互替换。这些策略算法是相同行为的不同实现。 需求 三国故事中,刘备要到江东娶孙权的妹妹孙尚香,由于这行...

zhang_pan
2018/04/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

聊聊flink TableEnvironment的scan操作

序 本文主要研究一下flink TableEnvironment的scan操作 实例 //Scanning a directly registered tableval tab: Table = tableEnv.scan("tableName")//Scanning a table from a registered......

go4it
9分钟前
0
0
JS检测移动端横竖屏的代码

移动端的设备提供了一个事件:orientationChange事件 这个事件是苹果公司为safari中添加的。以便开发人员能够确定用户何时将设备由横向查看切换为纵向查看模式。 在设备旋转的时候,会触发这...

不负好时光
9分钟前
0
0
ArrayList 优化

优化是 基于数据的大小 当数据量过大 (内存能抗住) 性能达到瓶颈才需要针对性的做优化 contain 优化 可以转换为set add 大批量操作 先预估数据量 调用 `ensureCapacity(int minCapacity)` ...

NotFound403
11分钟前
0
0
Lifecycle Aware Data Loading with Architecture Components

In my previous blog post, I talked about how you can use Loaders to load data in a way that automatically handles configuration changes. With the introduction of Architecture Co......

SuShine
11分钟前
0
0
性能测试汇总

服务器带宽测试 iperf测试带宽 wget -c https://codeload.github.com/esnet/iperf/tar.gz/3.1.6 tar zxvf 3.1.6cd iperf*yum install gcc./configure --prefix=/usr/local/iperf#指定......

以谁为师
15分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部