DES 加密解密类(Java 很好用)

package com.lu.util;

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class DES {

	public DES() {
	}

	public static DES getInstance(String key) throws NoSuchPaddingException,
			NoSuchAlgorithmException {
		return getInstance(getKeyByStr(key));
	}

	public static DES getInstance(byte key[]) throws NoSuchPaddingException,
			NoSuchAlgorithmException {
		DES des = new DES();
		if (des.key == null) {
			SecretKeySpec spec = new SecretKeySpec(key, "DES");
			des.key = spec;
		}
		des.cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
		return des;
	}

	public byte[] encrypt(byte b[]) throws InvalidKeyException,
			BadPaddingException, IllegalBlockSizeException,
			IllegalStateException {
		byte byteFina[] = null;
		cipher.init(1, key);
		byteFina = cipher.doFinal(b);
		return byteFina;
	}

	public byte[] decrypt(byte b[]) throws InvalidKeyException,
			BadPaddingException, IllegalBlockSizeException,
			IllegalStateException {
		byte byteFina[] = null;
		cipher.init(2, key);
		byteFina = cipher.doFinal(b);
		return byteFina;
	}

	public static byte[] getKeyByStr(String str) {
		byte bRet[] = new byte[str.length() / 2];
		for (int i = 0; i < str.length() / 2; i++) {
			Integer itg = new Integer(16 * getChrInt(str.charAt(2 * i))
					+ getChrInt(str.charAt(2 * i + 1)));
			bRet[i] = itg.byteValue();
		}
		return bRet;
	}

	private static int getChrInt(char chr) {
		int iRet = 0;
		if (chr == "0".charAt(0))
			iRet = 0;
		if (chr == "1".charAt(0))
			iRet = 1;
		if (chr == "2".charAt(0))
			iRet = 2;
		if (chr == "3".charAt(0))
			iRet = 3;
		if (chr == "4".charAt(0))
			iRet = 4;
		if (chr == "5".charAt(0))
			iRet = 5;
		if (chr == "6".charAt(0))
			iRet = 6;
		if (chr == "7".charAt(0))
			iRet = 7;
		if (chr == "8".charAt(0))
			iRet = 8;
		if (chr == "9".charAt(0))
			iRet = 9;
		if (chr == "A".charAt(0))
			iRet = 10;
		if (chr == "B".charAt(0))
			iRet = 11;
		if (chr == "C".charAt(0))
			iRet = 12;
		if (chr == "D".charAt(0))
			iRet = 13;
		if (chr == "E".charAt(0))
			iRet = 14;
		if (chr == "F".charAt(0))
			iRet = 15;
		return iRet;
	}

	private Key key;
	private Cipher cipher;

	/**
	 * @interpret 进行base64加密操作
	 * @param text
	 * @param keyString
	 * @return String
	 */
	public String encrypt(String text, String keyString) {
		String body = null;

		try {
			DES des = DES.getInstance(keyString);

			byte[] b = des.encrypt(text.getBytes("UTF8"));
			body = new String(Base64.encodeBase64(b));
		} catch (Exception ex) {

		}
		return body;
	}

	/**
	 * @interpret 进行base64进行解密
	 * @param text
	 * @param keyString
	 * @return String
	 */
	public String decrypt(String text, String keyString) {
		String body = null;
		try {
			DES des = DES.getInstance(keyString);

			byte[] b = Base64.decodeBase64(text.getBytes());

			body = new String(des.decrypt(b), "UTF8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return body;
	}
	/**
	 * 
	 * @param content  内容
	 * @param operation 加密或解密
	 * @param key 使用到的密钥:固定长度
	 * @return
	 */
	public String authcode(String content, String operation, String key){
		
		String encontent = null;
		if (operation != null && operation.equals("DECODE")) {
			encontent = encrypt(content,key);
		} else if (operation != null && operation.equals("ENCODE")) {
			encontent = decrypt(content,key);
		}
		return encontent;
	}

	public static void main(String[] args) {
		DES des = new DES();
		System.out.println(des.authcode("wewweewewew=","DECODE","0102030405060708"));//加密
		System.out.println(des.authcode("d8fPhfd9JkW99p8aqhtVIA==","ENCODE","0102030405060708"));//解密
	}
}


背景


在讨论 DES 之前,首先了解一下什么是对称加密算法吧。对于对称加密算法,他应用的时间比较早,技术相对来说比较成熟,在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。



在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。对称加密算法的特点是算法公开、计算量小。不足之处是,交易双方都使用同样钥匙,安全性得不到保证。


概念


那么,什么是 DES?他是怎么来的?相信很多人都很感兴趣,因为以前在开发的时候,对进度的要求比较严,很多时候根本就没有时间来了解这些东西。因此,今天专门来研究研究这个东西。

DES,全称为“Data Encryption Standard”,中文名为“数据加密标准”,是一种使用密钥加密的块算法。DES 算法为密码体制中的对称密码体制,又被称为美国数据加密标准,是 1972 年美国 IBM 公司研制的对称密码体制加密算法。 明文按 64 位进行分组,密钥长 64 位,密钥事实上是 56 位参与 DES 运算(第8、16、24、32、40、48、56、64 位是校验位, 使得每个密钥都有奇数个 1)分组后的明文组和 56 位的密钥按位替代或交换的方法形成密文组的加密方法。


基本原理


入口参数有三个:key、data、mode。key 为加密解密使用的密钥,data 为加密  解密的数据,mode 为其工作模式。当模式为加密模式时,明文按照 64 位进行分组,形成明文组,key 用于对数据加密,当模式为解密模式时,key 用于对数据解密。实际运用中,密钥只用到了 64 位中的 56 位,这样才具有高的安全性。




主要流程


DES 算法把 64 位的明文输入块变为 64 位的密文输出块,它所使用的密钥也是 64 位,其算法主要分为两步:

  • 初始置换
其功能是把输入的 64 位数据块按位重新组合,并把输出分为 L0、R0 两部分,每部分各长 32 位,其置换规则为将输入的第 58 位换到第一位,第 50 位换到第 2 位 …… 依此类推,最后一位是原来的第 7 位。L0、R0 则是换位输出后的两部分,L0 是输出的左 32 位,R0 是右  32 位,例:设置换前的输入值为 D1 D2 D3 …… D64,则经过初始置换后的结果为:L0 = D58 D50 …… D8;R0 = D57 D49 …… D7。

  • 逆置换
经过 16 次迭代运算后,得到 L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出。

整个算法 的主流程图如下:




分组模式


  • ECB模式

ECB,中文名“电子密码本模式”,是最古老、最简单的模式,将加密的数据分成若干组,每组的大小跟加密密钥长度相同。然后每组都用相同的密钥加密,比如 DES 算法,如果最后一个分组长度不够 64 位,要补齐 64 位。如图所示:



  • CBC模式

CBC,中文名“加密块链模式”,与 ECB 模式最大的不同是加入了初始向量。他的特点是,每次加密的密文长度为 64位 ( 8 个字节),当相同的明文使用相同的密钥和初始向量的时候 CBC 模式总是产生相同的密文。



  • CFB模式

CFB,中文名“加密反馈模式”,加密反馈模式克服了需要等待 8 个字节才能加密的缺点,它采用了分组密码作为流密码的密钥流生成器。他的特点是,每次加密的 Pi 和 Ci 不大于 64 位;加密算法和解密算法相同,不能适用于公钥算法;使用相同的密钥和初始向量的时候,相同明文使用 CFB 模式加密输出相同的密文;可以使用不同的初始化变量使相同的明文产生不同的密文,防止字典攻击;加密强度依赖于密钥长度;加密块长度过小时,会增加循环的数量,导致开销增加;加密块长度应时 8 位的整数倍(即字节为单位);一旦某位数据出错,会影响目前和其后 8 个块的数据。



  • OFB模式

OFB,中文名“输出反馈模式”,与 CFB 模式不同之处在于, 加密位移寄存器与密文无关了,仅与加密 key 和加密算法有关,做法是不再把密文输入到加密移位寄存器,而是把输出的分组密文(Oi)输入到一位寄存器。因为密文没有参与链操作,所以使得 OFB 模式更容易受到攻击;不会进行错误传播,某位密文发生错误,只会影响该位对应的明文,而不会影响别的位;不是自同步的,如果加密和解密两个操作失去同步,那么系统需要重新初始化;每次重新同步时,应使用不同的初始向量。可以避免产生相同的比特流,避免“已知明文”攻击。



  • CTR模式

CTR,中文名“计数模式”,是对一系列输入数据块(称为计数)进行加密,产生一系列的输出块,输出块与明文异或得到密文。对于最后的数据块,可能是长 u 位的局部数据块,这 u 位就将用于异或操作,而剩下的 b-u 位将被丢弃(b表示块的长度)。




猜你喜欢

转载自blog.csdn.net/qq_32445015/article/details/80184954