[color=cyan]DES加密算法基本知识[/color]
DES(Data Encryption Standard)又叫数据加密标准,是1973年5月15日美国国家标准局(现在是美国标准技术研究所,即NIST)在联邦记录中公开征集密码体制时出现的。DES由IBM开发,它是对早期被称为Lucifer体制的改进。DES在1975年3月17日首次在联邦记录中公布,在经过大量的公开讨论后,1977年2月15日DES被采纳为“非密级”应用的一个标准。最初预期DES作为一个标准只能使用10-15年,然而,事实证明DES要长寿得多。在其被采用后,大约每隔5年被评审一次。DES的最后一次评审是在1999年1月,在当时,一个DES的替代品,AES(Advanced Encryption Standard)开始使用。
DES是一种分组对称加解密算法,用64位密钥(实际用56位,其中每第八位作奇偶校验位)来加密(解密)64位数据,加密的过程伴随一系列的转换与代换操作。DES加密(解密)的过程可以分为两步:首先变换密钥得到56位密钥,然后据转换操作得到48位共16组子密钥。其次是用上面得到的16组子密钥加密(解密) 64位明(密)文,这个过程会有相应的S-BOX等的代换-转换操作。整个算法加密过程可以参考DES标准说明文件。

js代码(源代码见尾部附件(des.zip)) 

[color=red]注意:js加载顺序依次为 jquery.js,cryptojs-core.js,enc-base64.js,cipher-core.js,tripledes.js,mode-ecb.js[/color]

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<script type="text/javascript" src="./jquery.js"></script>
<script type="text/javascript" src="./cryptojs-core.js"></script>
<script type="text/javascript" src="./enc-base64.js"></script>
<script type="text/javascript" src="./cipher-core.js"></script>
<script type="text/javascript" src="./tripledes.js"></script>
<script type="text/javascript" src="./mode-ecb.js"></script>
<script type="text/javascript">

//DES 加密
function encryptByDES(message, key) {
        var keyHex = CryptoJS.enc.Utf8.parse(key);
        var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        });
        return encrypted.toString();
    }

//DES 解密
function decryptByDES(ciphertext, key) {
    var keyHex = CryptoJS.enc.Utf8.parse(key);
    // direct decrypt ciphertext
    var decrypted = CryptoJS.DES.decrypt({
        ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
    }, keyHex, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return decrypted.toString(CryptoJS.enc.Utf8);
}


var key = "AAAABBBB";  
var message = "武汉 湖北 中国";

//DES 加密
var encrypted = encryptByDES(message, key); 
//DES 解密
var decrypted = decryptByDES(encrypted, key);

document.writeln ("encrypted Test: " + encrypted);
document.writeln ("decrypted Test: " + decrypted);  

</script>
</head>
<body>

<h1>DES Demo.</h1>

</body>
</html>




java代码


Des.java


import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

/**
 * DES(Data Encryption Standard, 数据加密标准).<br>
 * Key为64位,去除64位中作为奇偶校验位的第8、16、24、32、40、48、56、64位,剩下的56位作为有效输入密钥.<br>
 * @author jason.zhong <br>
 * @version 1.0.0 2016年6月30日<br>
 * @see 
 */
public class Des {

	/**
	 * 日志记录器.
	 */
//	private static Log LOG = LogFactory.getLog(Des.class);

	/**
	 * DES加解密算法.
	 */
	protected static final String ALGORITHM_DES = "DES";

	/**
	 * DES填补方式.
	 * DES/CBC/PKCS5Padding. 
	 */
	protected static final String TRANSFORMATION_DES = "DES/ECB/Pkcs7";

	/**
	 * 构造函数(私有).
	 * @param algorithm 算法
	 * @param transformation 转换方式
	 */
	private Des(String algorithm, String transformation) {
	}

	/**
	 * 加密算法.
	 * @param data 需要加密的数据
	 * @param key 秘钥
	 * @return
	 */
	public static String encryptAsString(String data, String key) {
		byte[] bt = Des.encrypt(data.getBytes(), key.getBytes());
		return Base64.encryptAsString(bt);
	}

	/**
	 * 解密算法.
	 * @param data 需要解密的数据
	 * @param key 秘钥
	 * @return
	 */
	public static byte[] decryptAsByteArray(String data, String key) {
		if (data == null)
			return null;
		byte[] buf = Base64.decryptAsByteArray(data);
		return decrypt(buf, key.getBytes());
	}

	/**
	 * 解密算法
	 * @param data 需要解密的数据
	 * @param key 秘钥
	 * @return
	 */
	public static String decryptAsString(String data, String key) {
		if (data == null) {
			return null;
		}
		byte[] bt = decryptAsByteArray(data, key);
		return new String(bt);
	}

	/**
	 * 
	 * @param data
	 * @param key
	 * @return
	 */
	private static byte[] encrypt(byte[] data, byte[] key) {
		return doFinal(data, key, ALGORITHM_DES, TRANSFORMATION_DES, Cipher.ENCRYPT_MODE);
	}

	/**
	 * 
	 * @param data
	 * @param key
	 * @return
	 */
	private static byte[] decrypt(byte[] data, byte[] key) {
		return doFinal(data, key, ALGORITHM_DES, TRANSFORMATION_DES, Cipher.DECRYPT_MODE);
	}

	/**
	 * 加密/解密操作.
	 * @param data 需要操作的数据
	 * @param key 秘钥
	 * @param algorithm 
	 * @param transformation
	 * @param opmode
	 * @return
	 * @throws Exception
	 */
	private static byte[] doFinal(byte[] data, byte[] key, String algorithm, String transformation, int opmode) {
		byte[] result = null;
		try {
			// 创建秘钥工厂
//	        final SecretKey securekey = new SecretKeySpec(key, algorithm);


            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
            Key key2  = keyFactory.generateSecret(new DESKeySpec(key));  


	        // 加密/解密
	        final SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
	        final Cipher cipher = Cipher.getInstance("DES"); // transformation : the name of the transformation, e.g., DES/CBC/PKCS5Padding. 

	        cipher.init(opmode, key2, secureRandom);
	        result = cipher.doFinal(data);
		} catch (Exception e) {
//			if (LOG.isErrorEnabled()) {
//				LOG.error(new ExampleRuntimeException(e));
//			}
		}

		return result;
    }

	public static void main(String[] args) {
		final String plainText = "武汉 湖北 中国";
		final String key = "AAAABBBB";
		final String decodedText = Des.encryptAsString(plainText, key);
		System.out.println(decodedText);
		final String encodeText = Des.decryptAsString(decodedText, key);
		System.out.println(encodeText);
	}
}




Base64.java


/**
 * Base加解密.<br>
 * @author jason.zhong <br>
 * @version 1.0.0 2016年6月30日<br>
 * @see 
 * @since JDK 1.6.0
 */
public class Base64 {

	public static byte[] encryptAsByteArray(byte[] plainData) {
		return org.apache.commons.codec.binary.Base64.encodeBase64(plainData);
	}

	public static String encryptAsString(byte[] plainData) {
		final byte[] base64Data = encryptAsByteArray(plainData);
		return StringUtil.toUtf8String(base64Data);
	}

	public static byte[] encryptAsByteArray(String plainText) {
		final byte[] plainData = plainText.getBytes();
		return encryptAsByteArray(plainData);
	}

	public static String encryptAsString(String plainText) {
		final byte[] plainData = plainText.getBytes();
		return encryptAsString(plainData);
	}

	public static byte[] decryptAsByteArray(String base64String) {
		return org.apache.commons.codec.binary.Base64.decodeBase64(base64String.getBytes());
	}

	public static String decryptAsString(String base64String) {
		byte[] plainData = decryptAsByteArray(base64String);
		return StringUtil.toUtf8String(plainData);
	}

	public static void main(String[] args) {
		final String s = "武汉  湖北 中国";
		System.out.println(encryptAsString(s));
		System.out.println(decryptAsString(encryptAsString(s)));
	}
}




StringUtil.java


import java.io.UnsupportedEncodingException;


/**
 * 字符串工具类.<br>
 * @author jason.zhong <br>
 */
public final class StringUtil {

	/**
	 * 斜线.
	 */
	public static final char SLASH = '\u002f';

	/**
	 * 反斜线.
	 */
	public static final char BACK_SLASH = '\\';

	/**
	 * 点号.
	 */
	public static final char DOT = '\u002e';

	/**
	 * 逗号.
	 */
	public static final char COMMA = '\u002c';

	/**
	 * 空字符串"".
	 */
	public static final char EMPTY = '\u0000'; 

	/**
	 * 空格.
	 */
	public static final char SPACE = '\u0020';

	/**
	 * 左中括号.
	 */
	public static final char LEFT_BRACKET = '\u005b';

	/**
	 * 左中括号.
	 */
	public static final char RIGHT_BRACKET = '\u005d';

	/**
	 * UTF-8
	 */
	public static final String UTF_8 = "UTF-8";

	/**
	 * GBK
	 */
	public static final String GBK = "GBK";

	/**
	 * GB231
	 */
	public static final String GB2312 = "GB2312";

	/**
	 * 构造函数(私有)
	 */
	private StringUtil() { }

	/**
	 * 判断字符串是否是null或者空字符串.
	 * @param s 被判断的字符串
	 * @return 如果字符串为null或""则返回true,否则返回false.
	 */
	public static boolean hasText(String s) {
		if (null == s || s.length() == 0)  {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 根据Field的名字,按照Bean的规则,生产对应的Setter方法名.
	 * @param fieldName field名称
	 * @return Setter方法名称
	 */
	public static String getGetterMethodName(final String fieldName) {
		return "get" + upperCaseFirst(fieldName);
	}

	/**
	 * 根据Field的名字,按照Bean的规则,生产对应的Setter方法名.
	 * @param fieldName field名称
	 * @return Setter方法名称
	 */
	public static String getSetterMethodName(final String fieldName) {
		return "set" + upperCaseFirst(fieldName);
	}

	/**
	 * 将字符串的首字母变为大写.
	 * @param s
	 * @return
	 */
	public static String upperCaseFirst(final String s) {
		if (null == s || s.length() < 1) {
			return s;
		}

		return s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
	}

	/**
	 * 将字符串的首字母变为小写.
	 * @param s
	 * @return
	 */
	public static String lowerCaseFirst(final String s) {
		if (null == s || s.length() < 1) {
			return s;
		}

		return s.substring(0, 1).toLowerCase() + s.substring(1, s.length());
	}

    /**
	 * 格式化字符串.
	 * 将字符串中的{1}、{2}替换成%s,便于使用String.format方法.
	 * @param message
	 * @param arguments
	 */
	public static String formatString(String messages, Object... arguments) {
		final String regExp = "\\{\\d+\\}";
		return String.format(messages.replaceAll(regExp, "%s"), arguments);
	}

    /**
	 * 格式化字符串数组.
	 * @param message
	 * @param arguments
	 */
	public static String formatStringArray(String[] messages, Object... arguments) {
		if (null == messages || messages.length == 0) {
			return String.valueOf(EMPTY);
		}
		final StringBuilder sbMessage = new StringBuilder();
		for (int i=0; i < messages.length; i++) {
			sbMessage.append(messages[i]);
			if (i < messages.length - 1) {
				sbMessage.append(COMMA);
				sbMessage.append(SPACE);
			} else {
				sbMessage.append(DOT);
			}
		}

		return formatString(sbMessage.toString(), arguments);
	}

	/**
	 * 判断字符串转换为全小写后,是否为"true".
	 * @param s
	 * @return 如果指定的字符串不为空,而且忽略大小写后等于"true",那么返回true,否则返回false.
	 */
	public static boolean isTrue(String s) {
		return (s != null) && s.equalsIgnoreCase("true");
	}

	/**
	 * 将btye转化为UTF-8格式的字符串.
	 * @param data
	 * @return
	 */
	public static String toUtf8String(byte[] data) {
		String result = "";
		try {
			result = new String(data, UTF_8);
		} catch (UnsupportedEncodingException e) {
			// 这个异常不会产生.
		}

		return result;
	}
}