
<<EXpansion - Message Digest v3 (EXMD3-V6)>>
摘要:
EXMD3-V6 是一套以「跨語言確定性、舊環境可移植性、固定輸出格式」為核心目標的自定義雜湊組合。JavaScript 參考版本使用 ECMAScript 3 世代語法,設計目標為 Internet Explorer 6.0 至現代 Chrome;核心不依賴 WebCrypto、BigInt、TypedArray、Promise、TextEncoder、ES6 class 或 arrow function。
與 EXMD2 的自製 LCG 混合方式不同,EXMD3-V6 的核心建立在兩個不同的標準雜湊家族之上:SHA-512 與 SHA3-512。兩者經過 domain separation 與固定 framing 後形成 1024-bit composite seed,再以 SHA-512 + SHA3-512 共同驅動輸出階段,最後透過 rejection sampling 映射到固定 30 字元 alphabet。
- 跨時代 JavaScript 實作:只使用 ES3 世代即可表達的基本語法與 32-bit 位元運算;頁面載入時會執行 Known Answer Test,自我檢查 SHA-512、SHA3-512、Unicode 與固定 EXMD3 測試向量。
- 固定跨語言格式:輸出固定為 209 個 ASCII 字元,alphabet 固定為
rt478aGHLTdbADEFyu3MeRfhi6mnQj。Runtime 套件另外提供 PHP、VB6、Python、C++、C#、Java、iOS/Swift、Android/Kotlin、Windows x86 ASM、Standard C、VB.NET、Go、Ruby、Delphi、Perl。
- Unicode/UTF-16 一致性:參考模型以 JavaScript UTF-16 code unit 為基礎;成對 surrogate 會產生標準 UTF-8 百分比序列,孤立 surrogate 則保留其 code-unit 資訊,避免不同平台自動替換成 U+FFFD 後產生不同 Hash。
- 均勻的 radix-30 輸出:輸出階段只接受 0~239 的 byte,再對 30 取模;240~255 捨棄。因 240 可被 30 整除,可避免簡單 byte % 30 所造成的 modulo bias。
重要定位:EXMD3-V6 是自定義 composition,不是 NIST 標準化的新雜湊演算法,也不是密碼雜湊 KDF。請勿用它取代 Argon2、scrypt、bcrypt、PBKDF2 來儲存密碼;需要訊息認證請使用 HMAC,數位簽章請使用標準簽章演算法。
使用範例:
固定測試向量:
ex_md3("abc")
最小 JavaScript 使用方式:
<script src="https://cdn.jplopsoft.idv.tw/ex_md3.js"></script>
<script>
var hash = ex_md3("中文");
var hash2 = ex_md3n("abc", 2);
document.write(hash);
</script> |
JavaScript 檔案:https://cdn.jplopsoft.idv.tw/ex_md3.js
前一代 EXMD2 JavaScript:https://cdn.jplopsoft.idv.tw/ex_md2.js
瀏覽器書籤程式碼:
以下 Bookmarklet 會在需要時從 CDN 載入 ex_md3.js,再以 prompt 輸入文字並顯示結果:
EX_MD3N 疊代測試工具:
EXMD3-V6 每一輪包含多次 SHA-512 / SHA3-512 計算,成本遠高於 EXMD2。建議先從 1、10、100 次測試;大量疊代會暫時阻塞瀏覽器 UI,尤其在 IE6 或舊 CPU 上更明顯。
演算法流程:
- String coercion:輸入先轉為 JavaScript String,而且只轉換一次。
- UTF-16 / URI framing:透過
es1_safe_encodeURI() 建立確定性 ASCII 表示,並框入 UTF-16 長度、encoded 長度、固定 alphabet 與固定輸出長度 209。
- Dual-family seed:分別計算
SHA-512("EXMD3-V6-SHA512|" || frame) 與 SHA3-512("EXMD3-V6-SHA3-512|" || frame),串接成 128-byte seed。
- Counter-based squeeze:使用 32-bit big-endian counter,分別經 SHA-512 與 SHA3-512 產生候選 bytes。
- Rejection sampling:候選 byte 小於 240 才接受,最後用
value % 30 映射到固定 alphabet,直到輸出 209 字元。
設計目標:
EXMD3-V6 的目的不是「自行取代 SHA-512 / SHA3-512」,而是利用兩個成熟雜湊 primitive 建立一個跨語言、固定輸出 alphabet、可在舊 JavaScript runtime 執行的確定性指紋格式。
1. Time-Travel Compatibility
JavaScript 參考實作避免 ES5/ES6 之後才出現的語法與 API。演算法本體的設計目標為 IE6 / JScript 5.6 世代至現代 Chrome。不同實際瀏覽器仍建議執行頁面上的 Self-Test 進行 runtime 驗證。
2. Cross-Language Determinism
Runtime 套件以 JavaScript v6 參考行為為準,固定 framing、UTF-16 規則、SHA-512、SHA3-512、counter endian、rejection sampling、alphabet 與 209 字元輸出。
3. Domain Separation
seed 與 squeeze 階段,以及 SHA-512 與 SHA3-512 lane,都使用不同固定 domain prefix,避免把不同用途的 hash input 直接混在同一 namespace。
4. Deployment Friendly
新版語言可用原生/純語言實作;Windows 舊環境需要 helper 時,固定使用 <程式所在目錄>\lib\exmd3_core.exe,避免依賴 current working directory。
核心理念:
EXMD3-V6 將「演算法本體」與「輸出格式/跨語言協定」視為同一個版本規格。只要更改任一 framing prefix、alphabet 順序、Unicode 處理、counter endian 或輸出長度,都應視為新的、不相容版本,而不是偷偷修改 V6。
這種做法適合需要多年維持 deterministic identifier 的異質系統:老式 Windows 程式、Web 前端、Linux service、Java/Kotlin、iOS、IoT gateway 可以使用同一份測試向量驗證結果。
適合的用途:
- 跨語言資料指紋:同一份文字需要在 JavaScript、C、Java、Python、Go 等系統取得固定表示。
- 非機密的 deterministic ID:例如 cache key、內容索引、版本指紋、重複資料識別。
- 老舊系統整合:現代後端需要和 VB6、舊 PHP、Windows XP 時代程式共同計算同一結果。
- 自定義字元限制環境:輸出只能使用固定 30 字元 alphabet、不能使用十六進位或 Base64 時。
不建議:密碼儲存、API authentication secret、數位簽章、TLS 取代品、金融交易 MAC、需要正式密碼學認證的 protocol。這些用途應直接使用成熟標準。
安全與混淆特性:
1. 兩個不同標準 Hash family:seed 與 squeeze 同時使用 SHA-512(SHA-2 family)與 SHA3-512(Keccak/SHA-3 family)。這提供 family diversity,但 EXMD3-V6 本身仍是 custom construction,不能因此宣稱已經過與 NIST 標準相同程度的公開密碼分析。
2. 1024-bit composite seed:兩個 512-bit digest 串接成 128 bytes。209 個 radix-30 字元的表示容量約為 209 × log2(30) ≈ 1025.54 bits,因此足以承載這個輸出格式。
3. 無簡單 modulo bias:256 不能整除 30,所以直接 byte % 30 會讓部分字元略常出現;V6 捨棄 240~255,使接受範圍 240 正好等於 30 × 8。
4. Startup fail-closed:瀏覽器載入時會執行 SHA-512 / SHA3-512 KAT、Unicode 與 EXMD3 固定向量;若失敗直接 throw,不默默回傳錯誤 Hash。
5. Public alphabet tamper isolation:公開變數 EX_MD3_ALPHABET 只是相容介面;核心 alphabet 位於 closure 內,外部把公開變數改成其他值不會改變 Hash。
語言支援:
| 語言 / 平台 | 需要 lib/exmd3_core.exe? | Runtime 方式 |
| JavaScript | 不需要 | 直接載入 https://cdn.jplopsoft.idv.tw/ex_md3.js |
| PHP 4.3.11~8.x | 舊版需要 | 新版可原生;舊版 fallback 至 lib/exmd3_core.exe |
| Visual Basic 6.0 | 需要 | App.Path\lib\exmd3_core.exe,使用 UTF-16LE transport |
| Python | 不需要 | 獨立 Python 實作 |
| C++ | 不需要 | 使用 Standard C reference core |
| C# | 需要 | 程式目錄\lib\exmd3_core.exe,UTF-16LE transport |
| Java | 不需要 | 獨立 Java 實作 |
| iOS / Swift | 不需要 Windows EXE | Portable C core 編入 App |
| Android / Kotlin | 不需要 | 獨立 Kotlin/JVM 實作 |
| Windows x86 ASM | 需要 | 程式目錄\lib\exmd3_core.exe |
| Standard C | 不需要 | Reference core |
| VB.NET | 需要 | 程式目錄\lib\exmd3_core.exe,UTF-16LE transport |
| Go | 不需要 | 獨立 Go 實作 |
| Ruby | 不需要 | 獨立 Ruby 實作 |
| Delphi | 需要 | 程式目錄\lib\exmd3_core.exe,UTF-16LE transport |
| Perl | 需要 | 程式目錄\lib\exmd3_core.exe |
各語言最小使用範例:
JavaScript
<script src="https://cdn.jplopsoft.idv.tw/ex_md3.js"></script>
<script>
var result = ex_md3("中文");
document.write(result);
</script> |
PHP
<?php
require_once dirname(__FILE__) . "/ex_md3_v6.php";
echo ex_md3("中文");
?> |
VB6
' 專案加入 ExMd3V6.bas
' 部署:
' YourProgram.exe
' lib\exmd3_core.exe
Dim result As String
result = ex_md3("中文")
MsgBox result |
Python
from ex_md3_v6 import ex_md3, ex_md3n
print(ex_md3("中文"))
print(ex_md3n("abc", 2)) |
C++
#include "ex_md3_v6.hpp"
#include <iostream>
int main() {
std::string out = exmd3v6::hash_utf8("中文");
std::cout << out << std::endl;
} |
C#
// 專案加入 ExMd3V6.cs
// 部署:YourProgram.exe + lib\exmd3_core.exe
string result = ExMd3V6.Hash("中文");
Console.WriteLine(result); |
Java
System.out.println(ExMd3V6.exMd3("中文"));
System.out.println(ExMd3V6.exMd3n("abc", 2)); |
Swift
let result = ExMd3V6.hash("中文")
print(result) |
Kotlin
println(ExMd3V6.exMd3("中文"))
println(ExMd3V6.exMd3n("abc", 2)) |
C
#include "ex_md3_v6.h"
#include <stdio.h>
char out[210];
if (ex_md3_utf8("中文", out)) {
printf("%s\n", out);
} |
VB.NET
Dim result As String = ExMd3V6.ExMd3("中文")
Console.WriteLine(result)
' lib\exmd3_core.exe 與主程式相對部署 |
Go
package main
import (
"fmt"
"exmd3local/exmd3"
)
func main() {
h, err := exmd3.ExMD3("中文")
if err != nil { panic(err) }
fmt.Println(h)
} |
Ruby
require_relative "ex_md3_v6"
puts ExMd3V6.ex_md3("中文") |
Delphi
var
ResultText: string;
begin
ResultText := ExMd3('中文');
Writeln(ResultText);
end;
// lib\exmd3_core.exe 與程式相對部署 |
Perl
use FindBin;
use lib $FindBin::Bin;
use ExMd3V6 qw(ex_md3 ex_md3n);
print ex_md3("中文"), "\n"; |
EXMD3-V6 Runtime 完整套件下載:
ZIP SHA-256:
a09a4807612a56e5376b380bc1437f383cb9eab706ff3097edbf5a9b4ee4f2a5
下載按鈕使用 atob / Uint8Array / Blob;因此下載功能需要較新的瀏覽器。這項限制只影響 Base64 ZIP 下載按鈕,不代表 EXMD3 JavaScript 核心無法在 IE6 執行。
部署 Windows Helper:
需要 native fallback 的語言一律採用:
程式所在路徑\
├─ YourProgram.exe / a.php
└─ lib\
└─ exmd3_core.exe
Helper 不以 current working directory 為基準。Windows 上可先執行:
lib\exmd3_core.exe --selftest
預期輸出:
PASS EXMD3-V6 selftest UTF8+UTF16
版本相容性與變更規則:
EXMD3-V6 的輸出是版本協定的一部分。如果日後需要修改 alphabet、輸出長度、domain prefix、Unicode 規則或 hash family,建議建立 EXMD3-V7,而不要讓同名 V6 在不同系統產生不同結果。
結語:
EXMD3-V6 的重點不是「比 SHA-512 更標準」,而是把兩個成熟 Hash primitive、嚴格 Unicode framing、固定字元輸出與跨語言部署規則組成一套 deterministic format。它適合用於需要長期維持相同結果、又同時涵蓋新舊系統的工程場景。
對使用者而言,最簡單的驗證方式永遠是:載入 ex_md3.js 後先執行 ex_md3_selftest(),正常必須回傳 PASS;跨語言版本則使用相同的 ex_md3("abc") Known Answer Test 進行比對。
免責聲明與技術定位 (Disclaimer & Use Cases):
EXMD3-V6 以「現狀 (AS IS)」方式提供。它是自定義雜湊 composition 與跨語言格式,不是經 NIST 標準化的新 hash function。有限測試無法證明軟體 100% 永遠不存在 bug,也不能證明不存在未知 cryptanalytic weakness。
若用途涉及密碼儲存、authentication、金融交易、加密金鑰、數位簽章或其他高風險安全需求,請使用經廣泛審查的標準 protocol 與專用 primitive。
參閱文獻:
- NIST FIPS 180-4 — Secure Hash Standard (SHA-512 / SHA-2 family).
- NIST FIPS 202 — SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions.
- ECMA-262, ECMAScript Language Specification, 3rd Edition.
- MDN Web Docs — encodeURI() / JavaScript URI encoding behavior.
- Menezes, van Oorschot, Vanstone — Handbook of Applied Cryptography.
- 驗證工具:https://jplopsoft.idv.tw/utility_testutility_md.html
|