import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import org.apache.commons.lang.StringUtils;
import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;
/**
* MD5加密
* @author Administrator
*
*/
public class MD5Tool {
//向量(同時(shí)擁有向量和密匙才能解密),此向量必須是8byte,多少都報(bào)錯(cuò)
? ? private final byte[] DESIV = new byte[] { 0x22, 0x54, 0x36, 110, 0x40, (byte) 0xac, (byte) 0xad, (byte) 0xdf };// 向量? ?
? ? private AlgorithmParameterSpec iv = null;// 加密算法的參數(shù)接口
? ? private Key key = null;
? ? private String charset = "utf-8";
? ? public static void main(String[] args) {
? ? ? ? try {
? ? ? ? ? ? String value = "abcdefgh";
? ? ? ? ? ? String key = "121323324qwerty";// 自定義密鑰,個(gè)數(shù)不能太短硕蛹,太短報(bào)錯(cuò)吼蚁,過長(zhǎng)漩蟆,它默認(rèn)只取前N位(N的具體值罚斗,大家另行查找資料)
? ? ? ? ? ? MD5Tool mt= new MD5Tool(key, "utf-8");
? ? ? ? ? ? System.out.println("加密前的字符:" + value);
? ? ? ? ? ? System.out.println("加密后的字符:" + mt.encode(value));
? ? ? ? ? ? System.out.println("解密后的字符:" + mt.decode(mt.encode(value)));
? ? ? ? ? ? System.out.println("字符串的MD5值:"+getMD5Value(value));
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
? ? /**
? ? * 構(gòu)造函數(shù)
? ? * @param deSkey
? ? * @param charset
? ? * @throws Exception
? ? */
? ? public MD5Tool(String deSkey, String charset) throws Exception {
? ? ? ? if (StringUtils.isNotBlank(charset)) {
? ? ? ? ? ? this.charset = charset;
? ? ? ? }
? ? ? ? DESKeySpec keySpec = new DESKeySpec(deSkey.getBytes(this.charset));// 設(shè)置密鑰參數(shù)
? ? ? ? iv = new IvParameterSpec(DESIV);// 設(shè)置向量
? ? ? ? SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 獲得密鑰工廠
? ? ? ? key = keyFactory.generateSecret(keySpec);// 得到密鑰對(duì)象
? ? }
? ? /**
? ? * 加密
? ? * @param data
? ? * @return
? ? * @throws Exception
? ? */
? ? public String encode(String data) throws Exception {
? ? ? ? Cipher enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");// 得到加密對(duì)象Cipher
? ? ? ? enCipher.init(Cipher.ENCRYPT_MODE, key, iv);// 設(shè)置工作模式為加密模式跺株,給出密鑰和向量
? ? ? ? byte[] pasByte = enCipher.doFinal(data.getBytes(this.charset));
? ? ? ? BASE64Encoder base64Encoder = new BASE64Encoder();
? ? ? ? return base64Encoder.encode(pasByte);
? ? }
? ? /**
? ? * 解密
? ? * @param data
? ? * @return
? ? * @throws Exception
? ? */
? ? public String decode(String data) throws Exception {
? ? ? ? Cipher deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
? ? ? ? deCipher.init(Cipher.DECRYPT_MODE, key, iv);
? ? ? ? BASE64Decoder base64Decoder = new BASE64Decoder();
? ? ? ? //此處注意doFinal()的參數(shù)的位數(shù)必須是8的倍數(shù)郑什,否則會(huì)報(bào)錯(cuò)(通過encode加密的字符串讀出來都是8的倍數(shù)位府喳,但寫入文件再讀出來,就可能因?yàn)樽x取的方式的問題蘑拯,導(dǎo)致最后此處的doFinal()的參數(shù)的位數(shù)不是8的倍數(shù))
? ? ? ? //此處必須用base64Decoder钝满,若用data兜粘。getBytes()則獲取的字符串的byte數(shù)組的個(gè)數(shù)極可能不是8的倍數(shù),而且不與上面的BASE64Encoder對(duì)應(yīng)(即使解密不報(bào)錯(cuò)也不會(huì)得到正確結(jié)果)
? ? ? ? byte[] pasByte = deCipher.doFinal(base64Decoder.decodeBuffer(data));
? ? ? ? return new String(pasByte, this.charset);
? ? }
? ? /**
? ? * 獲取MD5的值弯蚜,可用于對(duì)比校驗(yàn)
? ? * @param sourceStr
? ? * @return
? ? */
? ? private static String getMD5Value(String sourceStr) {
? ? ? ? String result = "";
? ? ? ? try {
? ? ? ? ? ? MessageDigest md = MessageDigest.getInstance("MD5");
? ? ? ? ? ? md.update(sourceStr.getBytes());
? ? ? ? ? ? byte b[] = md.digest();
? ? ? ? ? ? int i;
? ? ? ? ? ? StringBuffer buf = new StringBuffer("");
? ? ? ? ? ? for (int offset = 0; offset < b.length; offset++) {
? ? ? ? ? ? ? ? i = b[offset];
? ? ? ? ? ? ? ? if (i < 0)
? ? ? ? ? ? ? ? ? ? i += 256;
? ? ? ? ? ? ? ? if (i < 16)
? ? ? ? ? ? ? ? ? ? buf.append("0");
? ? ? ? ? ? ? ? buf.append(Integer.toHexString(i));
? ? ? ? ? ? }
? ? ? ? ? ? result = buf.toString();
? ? ? ? } catch (NoSuchAlgorithmException e) {
? ? ? ? }
? ? ? ? return result;
? ? }
}