文档章节

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

翰霖学院
 翰霖学院
发布于 2017/07/24 08:58
字数 1830
阅读 5
收藏 1
点赞 0
评论 0

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

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
23种设计模式(12):策略模式

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

LCZ777
2014/07/09
0
0
简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

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

法斗斗
05/08
0
0
(目录)设计模式(可复用面向对象软件的基础)

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

chapin
2015/01/13
0
0
聚焦javascript的策略模式

今天看到一篇很好的文章和大家分享一下: 定义: 封装一系列的算法,使得他们之间可以相互替换,本模式使用算法独立于使用它的客户的变化。 说明:策略模式,是一种组织算法的模式,核心不在于...

xingongfang
2015/02/11
0
0
设计模式15——Template Method设计模式

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

小米米儿小
2014/01/24
0
0
js策略模式《JavaScript设计模式与开发实践》阅读笔记

策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且是它们可以相互替换。 策略模式可以避免代码中的多重判断条件。 策略模式很好的体现了开放-封闭原则,将一个个算法(解决方...

RoyLuo
05/19
0
0
设计模式.策略模式

策略模式跟抽象工厂非常相似,基本逻辑是根据需要实例化出需要用的类。不同的是策略模式需要调用者非常清晰的知道有哪些策略,各个策略的调用规则,而抽象工厂的话,需要知道有哪些类,找到调...

技术小胖子
2017/11/08
0
0
groovy 闭包【命令模式】

在Java编程世界,有两个设计模式又简单、又常用,而且实现方式也很相似,这就是命令模式和策略模式。 有关这两个模式的讲解,在网络上真是汗牛充栋,大家可以随便搜索一下,就是一大堆。 可以...

k_k_anna
2015/01/20
0
0
javascript 设计模式之工厂(Factory)模式

工厂模式介绍 工厂模式是一个创建型的模式,主要就是创建对象。其中工厂模式又分为简单工厂模式和抽象工厂模式。简单工厂模式是通过工厂方法确定创建 对应类型的对象。抽象工厂模式是通过子类...

hlxiong
2014/04/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

一款成功的全球服游戏该如何进行架构选型与设计?

全球服游戏如今正在成为出海游戏的主要考虑模式,跨国对战、全球通服打破国界的限制,将不同地区不同语言的玩家放在一起合作/竞技,成功吸引了大量玩家的关注,并逐渐成为主流的游戏玩法。 ...

UCloudTech
3分钟前
0
0
StringUtils类中isEmpty与isBlank的区别

org.apache.commons.lang.StringUtils类提供了String的常用操作,最为常用的判空有如下两种isEmpty(String str)和isBlank(String str)。 StringUtils.isEmpty(String str) 判断某字符串是否为...

说回答
16分钟前
0
0
react native使用redux快速上手

看例图 要求点击组件一中的按钮,改版组件二的背景色。 利用state和props和容易实现。 //app.jsimport React, {Component} from 'react';import {StyleSheet, Button, View, Text} from ...

燕归南
17分钟前
0
0
页面输出JSON格式数据

package com.sysware.utils;import java.io.IOException;import javax.servlet.ServletResponse;import org.apache.log4j.Logger;import com.sysware.SyswareConstant;pub......

AK灬
39分钟前
0
0
springCloud-2.搭建Eureka Client的使用

1.使用IDEA,Spring Initializr创建 2.填写项目资料 3.选择spring boot版本,插件选择Cloud Discovery→Eureka Discovery 4.选择保存地址 5.修改application.yml eureka: client: s...

贺小康
42分钟前
0
0
CenOS 6.5 RPM 安装 elasticsearch 6.3.1

下载 wget --no-check-certificate https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.1.rpm...

阿白
45分钟前
0
0
1.4 创建虚拟机&1.5 安装CentOS7&1.6 配置ip(上)&1.7 配置ip(下)

1.4 创建虚拟机 知识点 虚拟机网络链接模式 桥连 直接将虚拟网卡桥接到一个物理网卡上面。需要手工为虚拟系统配置IP地址、子网掩码,而且还要和宿主机器处于同一网段,这样虚拟系统才能和宿主...

小丑鱼00
51分钟前
0
0
TrustAsia(亚洲诚信)助力看雪2018安全开发者峰会

2018年7月21日,看雪2018安全开发者峰会在北京国家会议中心圆满落下帷幕。拥有18年悠久历史的老牌安全技术社区——看雪学院联手国内最大开发者社区CSDN,汇聚业内顶尖的安全开发者和技术专家...

亚洲诚信
52分钟前
0
0
Spring注解介绍

@Resource、@AutoWired、@Qualifier 都用来注入对象。其中@Resource可以以 name 或 type 方式注入,@AutoWired只能以 type 方式注入,@Qualifier 只能以 name 方式注入。 但它们有一些细微区...

lqlm
今天
0
0
32位汇编在64位Ubuntu上的汇编和连接

本教程使用的操作系统是Ubuntu Linux 18.04 LTS版本,汇编器是GNU AS(简称as),连接器是GNU LD(简称ld)。 以下是一段用于检测CPU品牌的汇编小程序(cpuid2.s): .section .dataoutput...

ryanliue
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部