原文:http://hello-nick-xu.iteye.com/blog/2103781
在上一篇博客中已经简要的介绍了MD5、BASE64、DES、RSA等算法在Java中的具体应用。现在可以考虑对这些代码封装成一个工具类EncryptUtil,然后再补充一下Commons Codec对BASE64的扩展支持!
<一>. EncryptUtil工具类:
1. 使用commons-logging记录异常日志。
2. 提取常量字段、公共字段。
3. 提取公共方法:
createSecretKey(String key):Key
processCipher(byte[] processData, Key key, int opsMode, String algorithm):byte[]
4. EncryptUtil类的完整代码:
package com.excelsoft.common.crypto;
import java.io.IOException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class EncryptUtil {
private static Log logger = LogFactory.getLog(EncryptUtil.class);
private static final int KEY_SIZE = 1024;
private static final String MD5_ALGORITHM= "md5";
private static final String DES_ALGORITHM= "des";
private static final String RSA_ALGORITHM= "rsa";
private static final String SIGNATURE_ALGORITHM= "MD5withRSA";
private static MessageDigest md5;
private static BASE64Encoder encoder;
private static BASE64Decoder decoder;
private static SecureRandom random;
private static KeyPair keyPair;
private EncryptUtil() {
}
static {
try {
md5 = MessageDigest.getInstance(MD5_ALGORITHM);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
keyPair = keyPairGenerator.generateKeyPair();
}
catch (NoSuchAlgorithmException e) {
logger.error(e);
}
encoder = new BASE64Encoder();
decoder = new BASE64Decoder();
random = new SecureRandom();
}
public static String encryptMD5(String plainText) {
byte[] cipherData = md5.digest(plainText.getBytes());
StringBuilder builder = new StringBuilder();
for(byte cipher : cipherData) {
String toHexStr = Integer.toHexString(cipher & 0xff);
builder.append(toHexStr.length() == 1 ? "0" + toHexStr : toHexStr);
}
return builder.toString();
}
public static String encryptBASE64(byte[] plainData) {
return encoder.encode(plainData);
}
public static byte[] decryptBASE64(String cipherText) {
byte[] plainData = null;
try {
plainData = decoder.decodeBuffer(cipherText);
}
catch (IOException e) {
logger.error(e);
}
return plainData;
}
public static byte[] encryptDES(byte[] plainData, String key) {
return processCipher(plainData, createSecretKey(key), Cipher.ENCRYPT_MODE, DES_ALGORITHM);
}
public static byte[] decryptDES(byte[] cipherData, String key) {
return processCipher(cipherData, createSecretKey(key), Cipher.DECRYPT_MODE, DES_ALGORITHM);
}
private static SecretKey createSecretKey(String key) {
SecretKey secretKey = null;
try {
DESKeySpec keySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM);
secretKey = keyFactory.generateSecret(keySpec);
}
catch (Exception e) {
logger.error(e);
}
return secretKey;
}
private static byte[] processCipher(byte[] processData, Key key, int opsMode, String algorithm) {
try{
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(opsMode, key, random);
return cipher.doFinal(processData);
}
catch (Exception e) {
logger.error(e);
}
return null;
}
public static PrivateKey createPrivateKey() {
return keyPair.getPrivate();
}
public static PublicKey createPublicKey() {
return keyPair.getPublic();
}
public static byte[] encryptRSA(byte[] plainData, Key key) {
return processCipher(plainData, key, Cipher.ENCRYPT_MODE, RSA_ALGORITHM);
}
public static byte[] decryptRSA(byte[] cipherData, Key key) {
return processCipher(cipherData, key, Cipher.DECRYPT_MODE, RSA_ALGORITHM);
}
public static byte[] createSignature(byte[] cipherData, PrivateKey privateKey) {
try {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey);
signature.update(cipherData);
return signature.sign();
}
catch (Exception e) {
logger.error(e);
}
return null;
}
public static boolean verifySignature(byte[] cipherData, byte[] signData, PublicKey publicKey) {
try {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey);
signature.update(cipherData);
return signature.verify(signData);
}
catch (Exception e) {
logger.error(e);
}
return false;
}
}
<二>. Commons Codec对BASE64的扩展支持:
JDK提供了对BASE64的标准支持,每隔76个字符进行换行\r\n,并且包含+、=、/等特殊字符不适合作为url参数传递。因此通常都会使用Commons Codec来进行BASE64的加密和解密。下载commons-codec-1.8.jar并添加到lib下面,注意选择高版本,低版本有些方法不支持。
1. 是否换行:
byte[] cipherData = Base64.encodeBase64(plainText.getBytes());
byte[] cipherData = Base64.encodeBase64(plainText.getBytes(), false);
byte[] cipherData = Base64.encodeBase64Chunked(plainText.getBytes());
String cipherText = Base64.encodeBase64String(plainText.getBytes());
2. 安全的url:转换+为-、/为_、将多余的=去掉
byte[] cipherData = Base64.encodeBase64(plainText.getBytes(), false, true);
byte[] cipherData = Base64.encodeBase64URLSafe(plainText.getBytes());
String cipherText = Base64.encodeBase64URLSafeString(plainText.getBytes());