首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java、JavaScript、Oracle、MySQL 跨平台 MD5 實作一致性指南

     編輯:Java 相關知識

跨語言/資料庫 MD5 雜湊一致性實作

MD5 (Message Digest Algorithm 5) 廣泛用於密碼雜湊、資料完整性驗證、快取鍵值生成等場景。但在 Java、JavaScript、MySQL、Oracle 等不同環境下實作時,常因大小寫差異、編碼方式、輸出格式 不一致導致驗證失敗。本文提供四大平台統一輸出小寫十六進制字串的標準實作,確保跨系統一致性。

核心一致性原則

  • 統一輸出格式:32 字元小寫十六進制字串 (如 c4ca4238a0b923820dcc509a6f75849b)
  • 統一輸入編碼:UTF-8 編碼字串轉位元組後再雜湊
  • 避免雙重雜湊差異:連續兩次 MD5 時,第一次輸出必須為小寫字串再輸入第二次

1. Java 實作 (標準庫)

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.nio.charset.StandardCharsets;

public class MD5Util {
    /**
     * 計算字串 MD5,回傳 32 位小寫十六進制字串
     */
    public static String md5(String input) {
        if (input == null) input = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
            
            StringBuilder sb = new StringBuilder(32);
            for (byte b : digest) {
                sb.append(String.format("%02x", b & 0xff));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 算法不可用", e);
        }
    }

    // 測試
    public static void main(String[] args) {
        String s1 = md5("1");
        String s2 = md5(s1); // 雙重 MD5
        System.out.println("md5('1') = " + s1);
        System.out.println("md5(md5('1')) = " + s2);
        // 輸出:
        // md5('1') = c4ca4238a0b923820dcc509a6f75849b
        // md5(md5('1')) = 28c8edde3d61a0411511d3b1866f0636
    }
}

2. MySQL 實作

MySQL 內建 MD5() 函數直接回傳小寫十六進制字串,完全符合標準:

-- 單次 MD5
SELECT MD5('1') AS m1;
-- 結果: c4ca4238a0b923820dcc509a6f75849b

-- 雙重 MD5 (注意: 內層結果已是小寫字串)
SELECT MD5(MD5('1')) AS m2;
-- 結果: 28c8edde3d61a0411511d3b1866f0636

-- 實務應用: 密碼雜湊儲存
INSERT INTO users (username, password_hash) 
VALUES ('admin', MD5(CONCAT('salt_', 'user_password')));

3. JavaScript 實作 (純 JS、無依賴)

推薦使用 blueimp/JavaScript-MD5 (約 3KB gzipped),支援 AMD/CommonJS/全域變數:

<script src="https://cdn.jsdelivr.net/npm/blueimp-md5@2.19.0/js/md5.min.js"></script>
<script>
    // 單次 MD5
    console.log(md5("1")); 
    // c4ca4238a0b923820dcc509a6f75849b

    // 雙重 MD5
    console.log(md5(md5("1"))); 
    // 28c8edde3d61a0411511d3b1866f0636

    // Node.js 環境
    // const md5 = require('blueimp-md5');

Node.js 原生實作 (無外部依賴):

const crypto = require('crypto');

function md5(str) {
    return crypto.createHash('md5').update(str, 'utf8').digest('hex');
}

console.log(md5("1"));           // c4ca4238a0b923820dcc509a6f75849b
console.log(md5(md5("1")));      // 28c8edde3d61a0411511d3b1866f0636

4. Oracle 實作

Oracle DBMS_OBFUSCATION_TOOLKIT.MD5 回傳大寫 RAW 型別,需轉換為小寫字串:

-- 建立包裝函數回傳標準小寫 VARCHAR2
CREATE OR REPLACE FUNCTION MD5_LOWER(p_text IN VARCHAR2) RETURN VARCHAR2 IS
    v_raw RAW(16);
    v_hex VARCHAR2(32);
BEGIN
    v_raw := DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING => p_text);
    v_hex := LOWER(RAWTOHEX(v_raw));
    RETURN v_hex;
END;
/

-- 測試
SELECT MD5_LOWER('1') AS m1, MD5_LOWER(MD5_LOWER('1')) AS m2 FROM dual;
-- M1: c4ca4238a0b923820dcc509a6f75849b
-- M2: 28c8edde3d61a0411511d3b1866f0636

驗證對照表

輸入JavaMySQLJavaScriptOracle (包裝後)
md5("1")c4ca4238a0b923820dcc509a6f75849bc4ca4238a0b923820dcc509a6f75849bc4ca4238a0b923820dcc509a6f75849bc4ca4238a0b923820dcc509a6f75849b
md5(md5("1"))28c8edde3d61a0411511d3b1866f063628c8edde3d61a0411511d3b1866f063628c8edde3d61a0411511d3b1866f063628c8edde3d61a0411511d3b1866f0636
md5("hello")5d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c592

安全性提醒

  • MD5 已不安全:可遭遇碰撞攻擊,嚴禁用於密碼儲存、數位簽章、SSL 憑證等安全敏感場景
  • 推薦替代方案:
    • 密碼雜湊:bcrypt、Argon2、PBKDF2 (含鹽值、可調整計算成本)
    • 資料完整性:SHA-256、SHA-3、BLAKE2
    • 訊息認證:HMAC-SHA256
  • 相容性場景:僅用於非安全場景,如快取鍵、資料去重、非敏感校驗和請求簽名
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved