abstrak:百度百科對MD5的說明是: Message Digest Algorithm MD5(中文名為消息摘要算法第 五版)為計算機安全領(lǐng)域廣泛使用的一種散列函數(shù),用以提供消息的完整性保護。MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現(xiàn)。將數(shù)據(jù)(如漢字)運
百度百科對MD5的說明是:
Message Digest Algorithm MD5(中文名為消息摘要算法第 五版)為計算機安全領(lǐng)域廣泛使用的一種散列函數(shù),用以提供消息的完整性保護。
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現(xiàn)。將數(shù)據(jù)(如漢字)運算為另一固定長度值,是雜湊算法的基礎(chǔ)原理,MD5的前身有MD2、MD3和MD4。
MD5算法具有以下特點:
1、壓縮性:任意長度的數(shù)據(jù),算出的MD5值長度都是固定的。
2、容易計算:從原數(shù)據(jù)計算出MD5值很容易。
3、抗修改性:對原數(shù)據(jù)進行任何改動,哪怕只修改1個字節(jié),所得到的MD5值都有很大區(qū)別。
4、強抗碰撞:已知原數(shù)據(jù)和其MD5值,想找到一個具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))是非常困難的。
MD5的作用是讓大容量信息在用數(shù)字簽名軟件簽署私人密鑰前被"壓縮"成一種保密的格式(就是把一個任意長度的字節(jié)串變換成一定長的十六進制數(shù)字串)。
通常采用java提供的API實現(xiàn)的MD5加密程序如下所示:
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Encryption1 { public static final String MD5="MD5"; /** * 采用加密算法加密字符串數(shù)據(jù) * @param str 需要加密的數(shù)據(jù) * @param algorithm 采用的加密算法 * @return 字節(jié)數(shù)據(jù) */ public static byte[] EncryptionStr(String str, String algorithm) { // 加密之后所得字節(jié)數(shù)組 byte[] bytes = null; try { // 獲取MD5算法實例 得到一個md5的消息摘要 MessageDigest md = MessageDigest.getInstance(algorithm); //添加要進行計算摘要的信息 md.update(str.getBytes()); //得到該摘要 bytes = md.digest(); } catch (NoSuchAlgorithmException e) { System.out.println("加密算法: "+ algorithm +" 不存在: "); } return null==bytes?null:bytes; } //測試上述方法 public static void main(String[] args) { String test1="test1"; String test2="QWERFVDSCX"; String test3="23423KJHkdfg"; String [] test={test1,test2,test3}; for (String s : test) { byte [] bytes=EncryptionStr(s,MD5); System.out.println("數(shù)據(jù):" + s+" 加密之后的結(jié)果為:"+bytes.toString()+" 字節(jié)數(shù)組長度為:"+bytes.length); } } }
上述代碼執(zhí)行結(jié)果為:
數(shù)據(jù):test1 加密之后的結(jié)果為:[B@71881149 字節(jié)數(shù)組長度為:16
數(shù)據(jù):QWERFVDSCX 加密之后的結(jié)果為:[B@1c2709da 字節(jié)數(shù)組長度為:16
數(shù)據(jù):23423KJHkdfg 加密之后的結(jié)果為:[B@46f7d5a6 字節(jié)數(shù)組長度為:16
分析:字符串采用MD5加密之后返回的數(shù)據(jù)類型為字節(jié)數(shù)組(byte []),一個字節(jié)是8位(bit位),返回的數(shù)組長度是16,那么加密的字符串結(jié)果為16*8=128位,為固定長度的字節(jié)數(shù)組,除了MD5代碼之外,上述代碼中algorithm參數(shù)改成SHA-1 、SHA-256等加密算法也是支持的
上述加密結(jié)果通常轉(zhuǎn)成長度為32的字符串進行存儲和傳輸,下面是程序代碼:
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Encryption2 { public static final String MD5="MD5"; /** * 采用加密算法加密字符串數(shù)據(jù) * @param str 需要加密的數(shù)據(jù) * @param algorithm 采用的加密算法 * @return 字節(jié)數(shù)據(jù) */ public static byte[] EncryptionStrBytes(String str, String algorithm) { // 加密之后所得字節(jié)數(shù)組 byte[] bytes = null; try { // 獲取MD5算法實例 得到一個md5的消息摘要 MessageDigest md = MessageDigest.getInstance(algorithm); //添加要進行計算摘要的信息 md.update(str.getBytes()); //得到該摘要 bytes = md.digest(); } catch (NoSuchAlgorithmException e) { System.out.println("加密算法: "+ algorithm +" 不存在: "); } return null==bytes?null:bytes; } /** * 把字節(jié)數(shù)組轉(zhuǎn)化成字符串返回 * @param bytes * @return */ public static String BytesConvertToHexString(byte [] bytes) { StringBuffer sb = new StringBuffer(); for (byte aByte : bytes) { String s=Integer.toHexString(0xff & aByte); if(s.length()==1){ sb.append("0"+s); }else{ sb.append(s); } } return sb.toString(); } /** * 采用加密算法加密字符串數(shù)據(jù) * @param str 需要加密的數(shù)據(jù) * @param algorithm 采用的加密算法 * @return 字節(jié)數(shù)據(jù) */ public static String EncryptionStr(String str, String algorithm) { // 加密之后所得字節(jié)數(shù)組 byte[] bytes = EncryptionStrBytes(str,algorithm); return BytesConvertToHexString(bytes); } //測試上述方法 public static void main(String[] args) { String test1="test1"; String test2="QWERFVDSCX"; String test3="23423KJHkdfg"; String [] test={test1,test2,test3}; for (String s : test) { String str=EncryptionStr(s,MD5); System.out.println("數(shù)據(jù):" + s+" 加密之后的結(jié)果為:"+str+" 字符串長度為:"+str.length()); } } }
上述代碼執(zhí)行結(jié)果為:
數(shù)據(jù):test1 加密之后的結(jié)果為:5a105e8b9d40e1329780d62ea2265d8a 字符串長度為:32
數(shù)據(jù):QWERFVDSCX 加密之后的結(jié)果為:ce5b403e336fb819b48b08dbfd39fbf3 字符串長度為:32
數(shù)據(jù):23423KJHkdfg 加密之后的結(jié)果為:6a91f81e7809f6f79c753a054543d128 字符串長度為:32
上述代碼雖然實現(xiàn)了基本的數(shù)據(jù)加密功能,但是有人可能覺得32位字符串還是太長了,想改成16位或者其他長度;或者說java編碼時工程統(tǒng)一使用UTF-8編碼,對字符串編碼格式進行指定等要求,下面是一種實現(xiàn)(功能可擴充點還有很多,比如說字符串數(shù)組加密,把加密之后的數(shù)據(jù)轉(zhuǎn)成指定編碼格式等)
import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Encryption3 { public static final String MD5="MD5"; public static final String UTF8="UTF-8"; /** * 采用加密算法加密字符串數(shù)據(jù) 轉(zhuǎn)成長度為32的字符串 * @param str * @param algorithm 采用的加密算法 * @param charset 指定轉(zhuǎn)化之后的字符串編碼 * @return */ public static String EncryptionStr32(String str, String algorithm,String charset) { // 加密之后所得字節(jié)數(shù)組 byte[] bytes = EncryptionStrBytes(str,algorithm,charset); return BytesConvertToHexString(bytes); } /** * 采用加密算法加密字符串數(shù)據(jù) 轉(zhuǎn)成長度為32的字符串 * @param str 需要加密的數(shù)據(jù) * @param algorithm 采用的加密算法 * @return 字節(jié)數(shù)據(jù) */ public static String EncryptionStr32(String str, String algorithm) { return EncryptionStr32(str,algorithm,""); } /** * 采用加密算法加密字符串數(shù)據(jù) 轉(zhuǎn)成長度為16的字符串 * @param str * @param algorithm 采用的加密算法 * @param charset 指定轉(zhuǎn)化之后的字符串編碼 * @return */ public static String EncryptionStr16(String str, String algorithm,String charset) { return EncryptionStr32(str,algorithm,charset).substring(8,24); } /** * 采用加密算法加密字符串數(shù)據(jù) 轉(zhuǎn)成長度為16的字符串 * @param str 需要加密的數(shù)據(jù) * @param algorithm 采用的加密算法 * @return 字節(jié)數(shù)據(jù) */ public static String EncryptionStr16(String str, String algorithm) { return EncryptionStr32(str,algorithm,"").substring(8,24); } /** * 采用加密算法加密字符串數(shù)據(jù) * @param str 需要加密的數(shù)據(jù) * @param algorithm 采用的加密算法 * @param charset 指定轉(zhuǎn)化之后的字符串編碼 * @return 字節(jié)數(shù)據(jù) */ public static byte[] EncryptionStrBytes(String str, String algorithm, String charset) { // 加密之后所得字節(jié)數(shù)組 byte[] bytes = null; try { // 獲取MD5算法實例 得到一個md5的消息摘要 MessageDigest md = MessageDigest.getInstance(algorithm); //添加要進行計算摘要的信息 if(null==charset||"".equals(charset)) { md.update(str.getBytes()); }else{ md.update(str.getBytes(charset)); } //得到該摘要 bytes = md.digest(); } catch (NoSuchAlgorithmException e) { System.out.println("加密算法: "+ algorithm +" 不存在: "); } catch (UnsupportedEncodingException e) { System.out.println("數(shù)據(jù)加密指定的編碼格式不支持: " + charset); } return null==bytes?null:bytes; } /** * 把字節(jié)數(shù)組轉(zhuǎn)化成字符串返回 * @param bytes * @return */ public static String BytesConvertToHexString(byte [] bytes) { StringBuffer sb = new StringBuffer(); for (byte aByte : bytes) { String s=Integer.toHexString(0xff & aByte); if(s.length()==1){ sb.append("0"+s); }else{ sb.append(s); } } return sb.toString(); } //測試上述方法 public static void main(String[] args) { String test1="test1"; String test2="QWERFVDSCX"; String test3="23423KJHkdfg"; String [] test={test1,test2,test3}; for (String s : test) { String str=EncryptionStr32(s, MD5, UTF8); System.out.println("數(shù)據(jù):" + s+" 加密之后的結(jié)果為:"+str+" 字符串長度為:"+str.length()); str = EncryptionStr16(s, MD5, UTF8); System.out.println("數(shù)據(jù):" + s+" 加密之后的結(jié)果為:"+str+" 字符串長度為:"+str.length()); } } }
程序運行結(jié)果:
數(shù)據(jù):test1 加密之后的結(jié)果為:5a105e8b9d40e1329780d62ea2265d8a 字符串長度為:32
數(shù)據(jù):test1 加密之后的結(jié)果為:9d40e1329780d62e 字符串長度為:16
數(shù)據(jù):QWERFVDSCX 加密之后的結(jié)果為:ce5b403e336fb819b48b08dbfd39fbf3 字符串長度為:32
數(shù)據(jù):QWERFVDSCX 加密之后的結(jié)果為:336fb819b48b08db 字符串長度為:16
數(shù)據(jù):23423KJHkdfg 加密之后的結(jié)果為:6a91f81e7809f6f79c753a054543d128 字符串長度為:32
數(shù)據(jù):23423KJHkdfg 加密之后的結(jié)果為:7809f6f79c753a05 字符串長度為:16