[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;
}
}