MD5的學習與練習
阿新 • • 發佈:2017-07-02
seq image fileinput 文本 canonical display 調用 substr 中文
(一)消息摘要簡介
一個消息摘要就是一個數據塊的數字指紋。即對一個任意長度的一個數據塊進行計算,產生一個唯一指印(對於SHA1是產生一個20字節的二進制數組)。消息摘要是一種與消息認證碼結合使用以確保消息完整性的技術。主要使用單向散列函數算法,可用於檢驗消息的完整性,和通過散列密碼直接以文本形式保存等,目前廣泛使用的算法由MD4、MD5、SHA-1.
消息摘要有兩個基本屬性:
1.兩個不同的報文難以生成相同的摘要
2.難以對指定的摘要生成一個報文,而可以由改報文反推算出該指定的摘要
代表:美國國家標準技術研究所的SHA1和麻省理工學院Ronald Rivest提出的MD5
(二)對字符串進行加密
MD5加密的Java實現
在各種應用系統中,如果需要設置賬戶,那麽就會涉及到存儲用戶賬戶信息的問題,為了保證所存儲賬戶信息的安全,通常會采用MD5加密的方式來,進行存儲。首先,簡單得介紹一下,什麽是MD5加密。
MD5的全稱是Message-Digest Algorithm 5 (信息-摘要算法),在90年代初,由MIT Laboratory for Computer Scientce 和RSA Data Security Inc 的 Ronald L.Rivest開發出來,經MD2、MD3和MD4發展而來。是讓大容量信息在用數字簽名軟件簽署私人密匙前被"壓縮"成一種保密的格式(就是把一個任意長度的字節串變換成一定長的大整數)。不管是MD2、MD4還是MD5,它們都需要獲得一個隨機長度的信息並產生一個128位的信息摘要。雖然這些算法的結構或多或少有些相似,但MD2的設計與MD4和MD5完全不同,那是因為MD2是為8位機器做過設計優化的,而MD4和MD5卻是面向32位的電腦。這三個算法的描述和C語言源代碼在Internet RFCs 1321中有詳細的描述,這是一份最權威的文檔,由Ronald L.Rivest在1992年8月向IETF提交。
(一)消息摘要簡介
一個消息摘要就是一個數據塊的數字指紋。即對一個任意長度的一個數據塊進行計算,產生一個唯一指印(對於SHA1是產生一個20字節的二進制數組)。消息摘要是一種與消息認證碼結合使用以確保消息完整性的技術。主要使用單向散列函數算法,可用於檢驗消息的完整性,和通過散列密碼直接以文本形式保存等,目前廣泛使用的算法由MD4、MD5、SHA-1.
消息摘要有兩個基本屬性:
1.兩個不同的報文難以生成相同的摘要
2.難以對指定的摘要生成一個報文,而可以由改報文反推算出該指定的摘要
代表:美國國家標準技術研究所的SHA1和麻省理工學院Ronald Rivest提出的MD5
(二)對字符串進行加密
package test; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import sun.misc.BASE64Encoder; /** * 對字符串進行加密 * @param str 待加密的字符串 * @return 加密後的字符串 * @throws NoSuchAlgorithmException 沒有這種產生消息摘要的算法 *@throws UnsupportedEncodingException */ public class Demo01 { public static String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException{ //確定算法 MessageDigest md5 = MessageDigest.getInstance("MD5"); BASE64Encoder base64en = new BASE64Encoder(); //加密後的字符串 String newstr = base64en.encode(md5.digest(str.getBytes("utf-8"))); return newstr; } public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException { String str = "0123456789"; System.out.println(EncoderByMd5(str)); } }
(三)驗證密碼是否正確
package test; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; /** * 判斷用戶密碼是否正確 * @param newpasswd 用戶輸入的密碼 * @param oldpasswd 數據庫中存儲的密碼--用戶密碼的摘要 * @return * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException * */ public class Demo02 { public static boolean checkpassword(String newpasswd, String oldpasswd) throws NoSuchAlgorithmException, UnsupportedEncodingException{ if (Demo01.EncoderByMd5(newpasswd).equals(oldpasswd)) { return true; } else { return false; } } public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException { System.out.println("old:"+Demo01.EncoderByMd5("123")); System.out.println("new:"+Demo01.EncoderByMd5("123")); System.out.println(checkpassword("123",Demo01.EncoderByMd5("123"))); } }
因為MD5是基於消息摘要原理的,消息摘要的基本特征就是很難根據摘要推算出消息報文,因此要驗證密碼是否正確,就必須對輸入密碼(消息報文)重新計算其摘要,和數據庫中存儲的摘要進行對比(即數據庫中存儲的其實為用戶密碼的摘要),若兩個摘要相同,則說明密碼正確,不同,則說明密碼錯誤。
練習:
package test; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Java實現MD5加密算法(使用MessageDigest) * MD5加密算法,即"Message-Digest Algorithm 5 (信息-摘要算法)",它由MD2、MD3、 * MD4發展而來的一種單向函數算法(也就是HASH算法),它是國際著名的公鑰加密算法標準RSA的第一設計者 * R.Rivest於上個世紀90年代初開發而來的。MD5的最大作用在於,將不同格式的大容量文件信息在用數字簽名 * 軟件來簽署私人秘鑰前"壓縮"成一種保密格式,關鍵之處在於--這種"壓縮"是不可逆的。Java JDK已經自帶 * 了MD5的實現,只要簡單調用下就可以。 * * @author Administrator * */ public class CreateMD5 { //靜態方法,便於工具類 public static String getMd5(String plainText){ try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(plainText.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)); } //32位加密 return buf.toString(); // 16位的加密 // return buf.toString().substring(8,24); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } public static void main(String[] args) { //測試 System.out.println(CreateMD5.getMd5("hello")); } }Java實現MD5加密算法
package test; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * 使用java獲取md5值的兩種方法 * 1.Message Digest Algorithm MD5 (中文名為消息摘要算法第五版) * 為計算機安全領域廣泛使用的一種散列函數,是一種比較常用的哈希算法。 * 2.導入包:commons-codec * @author Administrator * */ public class md5_test { //MD5的字符串常量 private final static String[] hexDigits = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"}; public static void main(String[] args) { try { MessageDigest messageDigest = MessageDigest.getInstance("MD5"); System.out.println(byteArrayToHexString(messageDigest.digest("baidu.com".getBytes()))); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } private static String byteArrayToHexString(byte[] b) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) { resultSb.append(byteToHexString(b[i])); } return resultSb.toString(); } /** * 將一個字節轉化成十六進制形式的字符串 * * @param b * @return */ private static String byteToHexString(byte b) { int n = b; if (n < 0) n = 256 + n; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1]+hexDigits[d2]; } }使用java獲取md5值的兩種方法
package test; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * MD5加密 * @author Administrator * */ public class MD5 { public static void main(String[] args) { System.out.println(MD5.getMD5("123456")); } /** * 用md5 編碼後的碼值 * * @param sInput * 明碼 * @return md5加密後的密碼 */ private static String getMD5(String sInput) { String algorithm =""; if (sInput == null) { return "null"; } try { algorithm = System.getProperty("MD5.algorithm","MD5"); } catch (SecurityException se) { } MessageDigest md = null; try { md = MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } byte buffer[] = sInput.getBytes(); for (int count = 0; count < sInput.length(); count++) { md.update(buffer,0,count); } byte bDigest[] = md.digest(); BigInteger bi = new BigInteger(bDigest); return (bi.toString(16)); } }MD5加密
package test; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.Security; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.apache.commons.codec.digest.DigestUtils; import sun.applet.Main; import sun.awt.image.BytePackedRaster; /** * java計算過G文件md5 值計算 * * @author Administrator * */ public class Md5CaculateUtil { private Md5CaculateUtil(){ } private static char[] hexChar = { ‘0‘,‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘,‘7‘,‘8‘,‘9‘, ‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘ }; public static String getHash(String fileName,String hashType) throws IOException, NoSuchAlgorithmException{ File f = new File(fileName); System.out.println("---------------------------------"); System.out.println("|當前文件名稱:"+f.getName()); System.out.println("|當前文件大小:"+f.length()/1024/1024+"MB"); System.out.println("|當前文件路徑[絕對]:"+f.getAbsolutePath()); System.out.println("|當前文件路徑[---]:"+f.getCanonicalPath()); System.out.println("---------------------------------"); InputStream ins = new FileInputStream(f); byte[] buffer = new byte[8192]; MessageDigest md5 = MessageDigest.getInstance(hashType); int len; while ((len = ins.read(buffer)) != -1) { md5.update(buffer, 0, len); } ins.close(); // 也可以用apache自帶的計算MD5方法 return DigestUtils.md5Hex(md5.digest()); // 自己寫的轉計算MD5方法 // return toHexString(md5.digest()); } public static String getHash2(String fileName){ File f = new File(fileName); return String.valueOf(f.lastModified()); } protected static String toHexString(byte[] b){ StringBuilder sb = new StringBuilder(b.length*2); for (int i = 0; i < b.length; i++) { sb.append(hexChar[(b[i] & 0xf0) >>> 4]); sb.append(hexChar[b[i] & 0x0f]); } return sb.toString(); } /** * 獲取MessageDigest支持幾種加密算法 */ @SuppressWarnings({"rawtypes","unchecked"}) private static String[] getCryptolmpls(String serviceType){ Set result = new HashSet(); // all prividers Provider[] providers = Security.getProviders(); for (int i = 0; i < providers.length; i++) { // get services provided by each provider Set keys = providers[i].keySet(); for (Iterator it = keys.iterator(); it.hasNext();) { String key = it.next().toString(); key = key.split(" ")[0]; if (key.startsWith(serviceType+".")) { result.add(key.substring(serviceType.length()+1)); } else if (key.startsWith("Alg.Alias."+serviceType+".")) { result.add(key.substring(serviceType.length(), 11)); } } } return (String[]) result.toArray(new String[result.size()]); } public static void main(String[] args) throws NoSuchAlgorithmException, IOException { // 調用方法 // String[] names = getCryptolmpls("MessageDigest"); // for(String name : names){ // System.out.println(name); // } long start = System.currentTimeMillis(); System.out.println("開始計算文件MD5值,請稍後..."); String fileName = "E:\\Office_2010_Tookit_2.2.3XiaZaiBa.zip"; // String fileName = "E:\\SoTowerStudio-3.1.0.exe"; String hashType = "MD5"; String hash = getHash(fileName, hashType); System.out.println("MD5"+hash); long end = System.currentTimeMillis(); System.out.println("一共耗時:"+(end-start)+"毫秒"); } }java計算過G文件md5 值計算
package test; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import exception.SpeedException; /** * Java三行代碼搞定MD5加密 * * 對字符串md5加密 * * @param str * @return * */ public class MD5Demo { public static String getMD5(String str) throws SpeedException{ try { // 生成一個MD5加密計算摘要 MessageDigest md = MessageDigest.getInstance("MD5"); // 計算md5函數 md.update(str.getBytes()); // digest()最後確定返回md5 hash值,返回值為字符串。因為md5 hash值是16位的hex值,實際上就是8位的字符 // BigInteger函數則將8位的字符串轉換成16位hex值,用字符串來表示,得到字符串形式的hash值 return new BigInteger(1,md.digest()).toString(16); } catch (Exception e) { throw new SpeedException("MD5加密出現錯誤"); } } public static void main(String[] args) throws SpeedException { System.out.println(getMD5("123"));; } }Java三行代碼搞定MD5加密
package test; import java.security.MessageDigest; /** * 利用Java自帶的MD5加密 * * @author Administrator * */ public class MD5Util { public final static String MD5(String s){ char hexDigits[]={‘0‘,‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘,‘7‘,‘8‘,‘9‘,‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘}; try { byte[] btInput = s.getBytes(); //獲得MD5摘要算法的 MessageDigest 對象 MessageDigest mdInst = MessageDigest.getInstance("MD5"); //使用指定的字節更新摘要 mdInst.update(btInput); //獲得密文 byte[] md = mdInst.digest(); //把密文轉換成十六進制的字符串形式 int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) { System.out.println(MD5Util.MD5("20121221")); System.out.println("加密"); } }利用Java自帶的MD5加密
package test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.math.BigInteger; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.security.MessageDigest; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; /** * Java讀取文件MD5的兩種方案 * 1.MessageDigest實現 * 2.org.apache.commons.codec.digest實現 * * @author Administrator * */ public class testMD5 { public static String getMd5ByFile(File file) throws FileNotFoundException{ String value = null; FileInputStream in = new FileInputStream(file); try { MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length()); MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(byteBuffer); BigInteger bi = new BigInteger(1,md5.digest()); value = bi.toString(16); } catch (Exception e) { e.printStackTrace(); } finally { if (null != in) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } return value; } public static void main(String[] args) throws IOException { String path ="E:\\commons-codec-1.10-bin.zip"; String v = getMd5ByFile(new File(path)); System.out.println("MD5:"+v.toUpperCase()); FileInputStream fis = new FileInputStream(path); String md5 = DigestUtils.md5Hex(IOUtils.toByteArray(fis)); IOUtils.closeQuietly(fis); System.out.println("MD5:"+md5); // System.out.println("MD5"+DigestUtils.md5Hex("WANGQIUYUN")); } }Java讀取文件MD5的兩種方案
package test; import org.apache.commons.codec.digest.DigestUtils; public class ToMain { public static void main(String[] args) { System.out.println(DigestUtils.md5Hex("baidu.com")); } }ToMain
package exception; public class SpeedException extends Exception { public SpeedException(String msg) { super(msg); } }SpeedException
MD5的學習與練習