文档章节

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

翰霖学院
 翰霖学院
发布于 2017/07/24 08:58
字数 1830
阅读 5
收藏 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
济南
高级程序员
Head First Design Pattern 读书笔记(1) 策略模式

Head First Design Pattern 读书笔记(1) Strategy Pattern 策略模式 这几天为了锻炼看英语文档的能力,开着有道硬着头皮看 《Head First Desgin Pattern》的原版书,顺便做下笔记,把里面提...

Tek_Eternal
2015/01/02
0
0
php各种设计模式简单实践思考

前言 我一直觉得什么框架,版本,甚至语言对于一个coder来说真的不算什么,掌握一个特别高大上的一个框架或者是一个新的,少众的语言真的不算什么,因为你可以,我要花时间也可以,大家都是这...

michaelgbw
2016/06/13
0
0
23种设计模式(12):策略模式

定义:定义一组算法,将每个算法都封装起来,并且使他们之间可以互换。 类型:行为类模式 类图: 策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,...

LCZ777
2014/07/09
0
0
(目录)设计模式(可复用面向对象软件的基础)

本系列“设计模式”博客使用Golang语言实现算法。所谓算法是指解决一个问题的步骤,个人觉得不在于语言。小弟只是最近学习Golang,所以顺带熟练一下语法知识,别无它意。 本系列博客主要介绍...

chapin
2015/01/13
0
0
简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

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

法斗斗
05/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

javascript source map 的使用

之前发现VS.NET会为压缩的js文添加一个与文件名同名的.map文件,一直没有搞懂他是用来做什么的,直接删除掉运行时浏览器又会报错,后来google了一直才真正搞懂了这个小小的map文件背后的巨大...

粒子数反转
昨天
0
0
谈谈如何学Linux和它在如今社会的影响

昨天,还在农耕脑力社会,今天已经人工智能技术、大数据、信息技术的科技社会了,高速开展并迅速浸透到当今科技社会的各个方面,Linux日益成为人们信息时代的到来,更加考验我们对信息的处理程...

linux-tao
昨天
0
0
学习设计模式——中介者模式

1. 认识中介者模式 1. 定义:用一个中介对象来封装一系列的对象交互行为,中介者使得各对象不需要显式的互相引用,从而使其松散耦合,独立的改变他们之间的交互。 2. 结构: Mediator:中介者...

江左煤郎
昨天
0
0
深入理解Plasma(1):Plasma 框架

这一系列文章将围绕以太坊的二层扩容框架,介绍其基本运行原理,具体操作细节,安全性讨论以及未来研究方向等。本篇文章作为开篇,主要目的是理解 Plasma 框架。 Plasma 作为以太坊的二层扩容...

HiBlock
昨天
0
0
Java 8 日期 示例

Java 8 推出了全新的日期时间API。Java处理日期、日历和时间的方式一直为社区所诟病,将 java.util.Date设定为可变类型,以及SimpleDateFormat的非线程安全使其应用非常受限。Java也意识到需...

阿刚ABC
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部