基於 VBScript 實現的對稱加密工具,採用十六進制編碼 + 異或 (XOR) 流加密模式,支援任意二進制檔案(圖片、文件、執行檔),透過 ADODB.Stream + XML DOM 實現二進制↔十六進制無損轉換。附帶完整加密/解密驗證流程。
| 決策點 | 選擇 | 理由 |
|---|---|---|
| 編碼格式 | 十六進制 | 可列印、無字元集問題、XML DOM 原生支援 bin.hex |
| 加密模式 | XOR 流加密 (Vernam Cipher 變體) | 實現簡單、加解密對稱、無需填充 |
| 金鑰處理 | 循環重複 (Repeating Key) | 支援任意長度金鑰、無需金鑰擴展算法 |
| 二進制讀寫 | ADODB.Stream (Type=1) | Windows 內建、高效、支援大檔案 |
| 十六進制轉換 | XML DOM Node (dataType="bin.hex") | 純腳本無需外部元件、自動處理編碼 |
' === XORCrypt.vbs ===
Option Explicit
Dim Key, startTime
Key = "www-enun-net" ' 金鑰:建議非純數字,長度 8-32 字元
' === 測試流程 ===
WScript.Echo Now & ", 加密開始"
Dim plainData, encData
plainData = ReadBinary("test.jpg")
encData = EncryptHex(plainData)
WriteBinary "E_test.jpg", encData
WScript.Echo Now & ", 加密完成"
WScript.Echo Now & ", 解密開始"
Dim decData
decData = ReadBinary("E_test.jpg")
Dim plainRestored
plainRestored = DecryptHex(decData)
WriteBinary "U_test.jpg", plainRestored
WScript.Echo Now & ", 解密完成"
' === 二進制檔案讀取:檔案 → 十六進制字串 ===
Function ReadBinary(filePath)
Dim stream, xmlDoc, node
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
Set node = xmlDoc.CreateElement("binary")
node.DataType = "bin.hex"
Set stream = CreateObject("ADODB.Stream")
stream.Type = 1 ' adTypeBinary
stream.Open
stream.LoadFromFile filePath
node.NodeTypedValue = stream.Read
stream.Close
ReadBinary = node.Text
Set node = Nothing: Set stream = Nothing: Set xmlDoc = Nothing
End Function
' === 十六進制字串寫入檔案 ===
Function WriteBinary(filePath, hexStr)
Dim stream, xmlDoc, node
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
Set node = xmlDoc.CreateElement("binary")
node.DataType = "bin.hex"
node.Text = hexStr
Set stream = CreateObject("ADODB.Stream")
stream.Type = 1
stream.Open
stream.Write node.NodeTypedValue
stream.SaveToFile filePath, 2 ' adSaveCreateOverWrite
stream.Close
Set stream = Nothing: Set node = Nothing: Set xmlDoc = Nothing
End Function
' === 加密:十六進制字串 → 異或 → 十六進制字串 ===
Function EncryptHex(hexStr)
Dim keyBytes, keyLen, i, j, byteVal, keyByte, encByte
hexStr = UCase(hexStr)
keyLen = Len(Key)
' 預計算金鑰位元組陣列 (ASCII 碼)
ReDim keyBytes(keyLen - 1)
For i = 0 To keyLen - 1
keyBytes(i) = Asc(Mid(Key, i + 1, 1))
Next
' 逐字節處理:十六進制字串每 2 字元 = 1 byte
Dim result, hexByte
result = ""
For i = 1 To Len(hexStr) Step 2
hexByte = Mid(hexStr, i, 2)
byteVal = CByte("&H" & hexByte)
keyByte = keyBytes(((i - 1) / 2) Mod keyLen)
encByte = byteVal Xor keyByte
result = result & Right("0" & Hex(encByte), 2) ' 確保 2 位十六進制
Next
EncryptHex = result
End Function
' === 解密:同加密邏輯 (XOR 可逆) ===
Function DecryptHex(hexStr)
Dim keyBytes, keyLen, i, byteVal, keyByte, decByte
hexStr = UCase(hexStr)
keyLen = Len(Key)
ReDim keyBytes(keyLen - 1)
For i = 0 To keyLen - 1
keyBytes(i) = Asc(Mid(Key, i + 1, 1))
Next
Dim result, hexByte
result = ""
For i = 1 To Len(hexStr) Step 2
hexByte = Mid(hexStr, i, 2)
byteVal = CByte("&H" & hexByte)
keyByte = keyBytes(((i - 1) / 2) Mod keyLen)
decByte = byteVal Xor keyByte
result = result & Right("0" & Hex(decByte), 2)
Next
DecryptHex = result
End Function
"FF00AB" (3 bytes: 0xFF, 0x00, 0xAB)Step 2 每次取 2 字元CByte("&H" & hexByte) 將十六進制字串轉 Byte 數值Hex(decByte) 轉回十六進制,Right("0" & ..., 2) 補零' i 為十六進制字串位置 (1-based, step 2)
' byteIndex = (i - 1) / 2 (0-based byte 索引)
' keyIndex = byteIndex Mod keyLen
' 等價於:每處理 1 個 byte,金鑰索引 +1,循環使用
' 寫入二進制 → 十六進制
node.DataType = "bin.hex"
node.NodeTypedValue = binaryData ' Variant(Byte())
hexStr = node.Text
' 十六進制 → 二進制
node.DataType = "bin.hex"
node.Text = hexStr
binaryData = node.NodeTypedValue ' 返回 Variant(Byte())
定性:流加密,但金鑰重複使用 → 多表代換密碼,非一次性密碼本 (OTP)。
弱點:
- 已知明文攻擊:若攻擊者知部分明文,可推導金鑰流片段
- 金鑰重複:長檔案中金鑰循環重複,統計分析可破解
- 無完整性驗證:密文修改解密後無法檢測
- 無認證:無法防止中間人竄改
適用場景:輕度混淆、非敏感資料臨時保護、教學演示。
嚴禁場景:機密資料、傳輸加密、長期儲存保護、任何合規要求場景。
| 檔案大小 | 十六進制字串長度 | 記憶體佔用 | 處理時間 (參考) |
|---|---|---|---|
| 1 MB | 2 MB | ~10 MB | < 1 秒 |
| 10 MB | 20 MB | ~100 MB | ~5 秒 |
| 100 MB | 200 MB | ~1 GB | ~60 秒 |
硬性限制:VBScript 字串長度上限 ~2GB (實際受限於 32 位元進程空間 ~1.5GB)。建議 單檔 < 50 MB。大檔案需分塊處理或改用串流式加密 (AES-GCM)。
Function EncryptFile_Streaming(srcPath, dstPath, key, Optional chunkSize = 1048576)
Dim srcStream, dstStream, xmlDoc, node, buffer, hexStr, encHex, i, keyBytes, keyLen
' 初始化金鑰
keyLen = Len(key)
ReDim keyBytes(keyLen - 1)
For i = 0 To keyLen - 1: keyBytes(i) = Asc(Mid(key, i + 1, 1)): Next
Set srcStream = CreateObject("ADODB.Stream")
srcStream.Type = 1: srcStream.Open: srcStream.LoadFromFile srcPath
Set dstStream = CreateObject("ADODB.Stream")
dstStream.Type = 1: dstStream.Open
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
Set node = xmlDoc.CreateElement("binary")
node.DataType = "bin.hex"
Dim byteIndex, keyByte, byteVal, encByte, hexByte
byteIndex = 0
Do Until srcStream.EOS
buffer = srcStream.Read(chunkSize)
node.NodeTypedValue = buffer
hexStr = node.Text
' 加密十六進制字串
encHex = ""
For i = 1 To Len(hexStr) Step 2
hexByte = Mid(hexStr, i, 2)
byteVal = CByte("&H" & hexByte)
keyByte = keyBytes(byteIndex Mod keyLen)
encByte = byteVal Xor keyByte
encHex = encHex & Right("0" & Hex(encByte), 2)
byteIndex = byteIndex + 1
Next
' 寫入加密後二進制
node.Text = encHex
dstStream.Write node.NodeTypedValue
Loop
dstStream.SaveToFile dstPath, 2
srcStream.Close: dstStream.Close
End Function
# 加密
$key = [System.Text.Encoding]::UTF8.GetBytes("My32ByteKeyForAES256GCM!!!!")
$plain = [IO.File]::ReadAllBytes("test.jpg")
$aes = [System.Security.Cryptography.AesGcm]::new($key)
$nonce = [System.Security.Cryptography.RandomNumberGenerator]::GetBytes(12)
$tag = New-Object byte[] 16
$cipher = New-Object byte[] $plain.Length
$aes.Encrypt($nonce, $plain, $cipher, $tag, [System.Text.Encoding]::UTF8.GetBytes("context"))
[IO.File]::WriteAllBytes("test.enc", $nonce + $cipher + $tag)
# 解密
$data = [IO.File]::ReadAllBytes("test.enc")
$nonce = $data[0..11]
$cipher = $data[12..($data.Length-17)]
$tag = $data[($data.Length-16)..($data.Length-1)]
$aes.Decrypt($nonce, $cipher, $tag, [System.Text.Encoding]::UTF8.GetBytes("context"), $plain)
[IO.File]::WriteAllBytes("test_dec.jpg", $plain)
總結:VBScript XOR 十六進制加密展示了腳本語言處理二進制資料的經典技巧 (ADODB.Stream + XML DOM),但其密碼學強度極低。理解其原理有助於掌握流加密基礎、十六進制編碼、COM 互操作,生產環境請毫不猶豫選用 AES-GCM / ChaCha20-Poly1305 等現代認證加密算法。