1 回答

TA貢獻1719條經驗 獲得超6個贊
代碼基本沒問題,只有幾個小問題:
CryptoJS 不會自動禁用流密碼模式(如 CTR)的默認 PKCS7 填充。因此,必須在 Go 代碼中應用 PKCS7 填充。
由于CryptoJS代碼使用內部的PBKDF,所以解密需要OpenSSL格式(即Salted__的ASCII編碼后跟8字節salt和實際密文),十六進制編碼。因此 Go 代碼必須相應地格式化和編碼數據。
CryptoJS在使用內部 PBKDF 時派生密鑰和 IV 。因此,在 CryptoJS 代碼中,指定的 IV在解密過程中被忽略。因此,在 Go 代碼中,可以指定任何IV。
以下代碼對應于您的代碼,由 PKCS#7 填充和結果的格式/編碼擴展(考慮代碼中的注釋)。請注意,與您的代碼一樣,為了簡單起見,使用了硬編碼鹽,但實際上出于安全原因,必須應用隨機生成的鹽:
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
evp "github.com/walkert/go-evp"
"github.com/zenazn/pkcs7pad"
)
func main() {
rawKey := "46ca2a49c8074dadb99843f6b86c5975"
data := pkcs7pad.Pad([]byte("the quick brown fox jumps over the lazy dog"), 16) // 1. Pad the plaintext with PKCS#7
fmt.Println("padded data: ", hex.EncodeToString(data))
encryptedData := encrypt(rawKey, data)
fmt.Println("encrypted data: ", encryptedData)
}
func encrypt(rawKey string, plainText []byte) string {
salt := []byte("ABCDEFGH") // hardcoded at the moment
// Gets key and IV from raw key.
key, iv := evp.BytesToKeyAES256CBCMD5([]byte(salt), []byte(rawKey))
// Create new AES cipher block
block, err := aes.NewCipher(key)
if err != nil {
return err.Error()
}
cipherText := make([]byte, len(plainText))
// Encrypt.
encryptStream := cipher.NewCTR(block, iv)
encryptStream.XORKeyStream(cipherText, plainText)
ivHex := hex.EncodeToString(iv)
encryptedDataHex := hex.EncodeToString([]byte("Salted__")) + hex.EncodeToString(salt) + hex.EncodeToString(cipherText) // 2. Apply the OpenSSL format, hex encode the result
return ivHex + ":" + encryptedDataHex // 3. Any value for ivHex can be used here, e.g. "00000000000000000000000000000000"
}
輸出是:
padded data: 74686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f670505050505
encrypted data: 3a010df5e7985f2d8b0c00e3a096347f:53616c7465645f5f41424344454647486036327f61cf3050fddd6ea76325148c81e170a63b514b8818afbbb894c874c87cc4c865300c7b2d0e0fd82826f3d3c5
可以使用遺留代碼解密此密文:
const decrypt = function (rawKey, encryptedData) {
const split = encryptedData.split(':');
if (split.length < 2) return '';
const reb64 = CryptoJS.enc.Hex.parse(split[1]);
const bytes = reb64.toString(CryptoJS.enc.Base64);
const hash = CryptoJS.AES.decrypt(bytes, rawKey, {
iv: split[0], // This is ignored if the internal PBKDF is used
mode: CryptoJS.mode.CTR
});
const plain = hash.toString(CryptoJS.enc.Utf8);
return plain;
}
const rawKey = '46ca2a49c8074dadb99843f6b86c5975';
const encryptedData = '3a010df5e7985f2d8b0c00e3a096347f:53616c7465645f5f41424344454647486036327f61cf3050fddd6ea76325148c81e170a63b514b8818afbbb894c874c87cc4c865300c7b2d0e0fd82826f3d3c5';
const decyptedData = decrypt(rawKey, encryptedData);
document.getElementById("pt").innerHTML = "decrypted data: " + decyptedData;
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<p style="font-family:'Courier New', monospace;" id="pt"></p>
- 1 回答
- 0 關注
- 566 瀏覽
添加回答
舉報