MD5收集整理

MD5如何生成的

百度百科

md5

生成MD5

1.通過摘要生成MD5

 MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(input.getBytes(StandardCharsets.UTF_8));
        byte[] hashBytes = md.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : hashBytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();

2.使用Google的Guava生成MD5

  • 添加依賴
            <dependency>
              <groupId>com.google.guava</groupId>
              <artifactId>guava</artifactId>
              <version>28.1-jre</version>
          </dependency>
  • 生成代碼
  // com.google.common.hash.Hashing.md5()
         // If you must interoperate with a system that requires MD5, then use this method, despite its deprecation. But if you can choose your hash function, avoid MD5, which is neither fast nor secure. As of January 2017, we suggest:
         // For security: Hashing.sha256() or a higher-level API.
         // For speed: Hashing.goodFastHash(int), though see its docs for caveats.
         HashFunction hashFunction = Hashing.md5();
 
         HashCode hash = hashFunction.hashString(input, StandardCharsets.UTF_8);
         return hash.toString();

3.使用Appach的commons生成MD5

  • 添加依賴
<dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.13</version>
        </dependency>
  • 生成代碼
   String md5 = DigestUtils.md5Hex( input );
          return md5;

加鹽MD5

爲什麼加鹽

彩虹表是一個用於加密散列函數逆運算的預先計算好的表, 常用於破解加密過的密碼散列。一般主流的彩虹表都在100G以上。 查找表常常用於包含有限字符固定長度純文本密碼的加密。這是以空間換時間的典型實踐, 在每一次嘗試都計算的暴力破解中使用更少的計算能力和更多的儲存空間,但卻比簡單的每個輸入一條散列的翻查表使用更少的儲存空間和更多的計算性能。使用加鹽的KDF函數可以使這種攻擊難以實現。

什麼是鹽

  1. 密碼加鹽
  2. 本質就是增加要加密內容的單一性,使用複雜。比如:只對密碼加密->對用戶名和密碼加密(一個不對全不對)->對用戶名和密碼再加隨機數加密(爲了驗證,最終還是要報隨機數的位置確定,驗證前刪除掉)

如何加鹽

加鹽示例代碼

public static String createMd5WithSalt(String input) throws NoSuchAlgorithmException {
        // MessageDigest instance for MD5
        MessageDigest md = MessageDigest.getInstance("MD5");

        // Generate the random salt
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[16];
        random.nextBytes(salt);
        md.update(salt);
        md.update(input.getBytes(StandardCharsets.UTF_8));
        byte[] hashBytes = md.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : hashBytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

加鹽並能重複驗證

  1. 一般一個系統會使用一個固定格式的鹽 如用戶名加密

  2. 也有使用固定位數的鹽的,如把鹽按一定規律插入到生面的md5中,驗證時從中取出鹽,然後再校驗

      private static Integer SALT_LENGTH = 16;
       private static Integer SALT_MD5_LENGTH = 48;
       private static Integer STEP_LENGTH = 3;
   public static String createMd5WithSalt(String input) throws NoSuchAlgorithmException {
   
            // 生成一個16位的隨機數
           SecureRandom random = new SecureRandom();
           StringBuilder sBuilder = new StringBuilder(16);
           sBuilder.append(random.nextInt(66888888)).append(random.nextInt(66888888));
           int len = sBuilder.length();
           if (len < SALT_LENGTH) {
               for (int i = 0; i < SALT_LENGTH - len; i++) {
                   sBuilder.append("0");
               }
           }
           // 生成最終的加密鹽
           String Salt = sBuilder.toString();
           String saltMd5 = createMd5(input + Salt);
           char[] cs = new char[SALT_MD5_LENGTH];
           for (int i = 0; i < SALT_MD5_LENGTH; i += STEP_LENGTH) {
               cs[i] = saltMd5.charAt(i / 3 * 2);
               char c = Salt.charAt(i / 3);
               cs[i + 1] = c;
               cs[i + 2] = saltMd5.charAt(i / 3 * 2 + 1);
           }
           return String.valueOf(cs);
       }
   
       public static boolean verifyMd5WithSalt(String input, String md5str) throws NoSuchAlgorithmException {
           char[] cs1 = new char[32];
           char[] cs2 = new char[16];
           for (int i = 0; i < SALT_MD5_LENGTH; i += STEP_LENGTH) {
               cs1[i / 3 * 2] = md5str.charAt(i);
               cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);
               cs2[i / 3] = md5str.charAt(i + 1);
           }
           String Salt = new String(cs2);
           return createMd5(input + Salt).equals(String.valueOf(cs1));
       }
   
   // 使用
    // 加鹽
               String md5WithSalt = MessageDigestCreate.createMd5WithSalt("測試md5");
               System.out.println(md5WithSalt);
               System.out.println(MessageDigestCreate.verifyMd5WithSalt("測試md5",md5WithSalt));
   /**
   125214383c3b755320902731b46d79344914f2199c786272
   true
   */
   
  • 建議使用安全隨機數。
  • 其它幾種方式加鹽同理,只是生面md5的來源不同
  • 源碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章