Golang 中的 AES 256 CTR 加密 使用 CryptoJS 在 Node JS 中解密

我必须使用 golang 将数据发送到具有 nodejs 加密的现有(遗留)服务,该服务将使用 AES CTR 模式和 Crypto JS libray 解密数据。我做了一些代码如下(密钥加密是这个问题中的随机密钥)。


高朗加密:


func main() {

    rawKey := "46ca2a49c8074dadb99843f6b86c5975"

    data := "the quick brown fox jumps over the lazy dog"

    

    encryptedData := encrypt(rawKey, data);

    fmt.Println("encrypted data: ", encryptedData)

}


func encrypt(rawKey string, data string) string {

    key := []byte(rawKey)

    plainText := []byte(data)


    // Create new AES cipher block

    block, err := aes.NewCipher(key)

    if err != nil {

        return err.Error()

    }


    // The IV (Initialization Vector) need to be unique, but not secure.

    // Therefore, it's common to include it at the beginning of the cipher text.

    cipherText := make([]byte, aes.BlockSize+len(plainText))


    // Creates IV.

    iv := cipherText[:aes.BlockSize]

    if _, err := io.ReadFull(rand.Reader, iv); err != nil {

        return err.Error()

    }


    // Encrypt.

    encryptStream := cipher.NewCTR(block, iv)

    encryptStream.XORKeyStream(cipherText[aes.BlockSize:], plainText)


    ivHex := hex.EncodeToString(iv)

    encryptedDataHex := hex.EncodeToString(cipherText)

    return encryptedDataHex[0:len(ivHex)] + ":" + encryptedDataHex[len(ivHex):]

}



噜噜哒
浏览 363回答 1
1回答

慕侠2389804

代码基本没问题,只有几个小问题:CryptoJS 不会自动禁用流密码模式(如 CTR)的默认 PKCS7 填充。因此,必须在 Go 代码中应用 PKCS7 填充。由于CryptoJS代码使用内部的PBKDF,所以解密需要OpenSSL格式(即Salted__的ASCII编码后跟8字节salt和实际密文),十六进制编码。因此 Go 代码必须相应地格式化和编码数据。CryptoJS在使用内部 PBKDF 时派生密钥和 IV 。因此,在 CryptoJS 代码中,指定的 IV在解密过程中被忽略。因此,在 Go 代码中,可以指定任何IV。以下代码对应于您的代码,由 PKCS#7 填充和结果的格式/编码扩展(考虑代码中的注释)。请注意,与您的代码一样,为了简单起见,使用了硬编码盐,但实际上出于安全原因,必须应用随机生成的盐:package mainimport (&nbsp; &nbsp; "crypto/aes"&nbsp; &nbsp; "crypto/cipher"&nbsp; &nbsp; "encoding/hex"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; evp "github.com/walkert/go-evp"&nbsp; &nbsp; "github.com/zenazn/pkcs7pad")func main() {&nbsp; &nbsp; rawKey := "46ca2a49c8074dadb99843f6b86c5975"&nbsp; &nbsp; data := pkcs7pad.Pad([]byte("the quick brown fox jumps over the lazy dog"), 16) // 1. Pad the plaintext with PKCS#7&nbsp; &nbsp; fmt.Println("padded data: ", hex.EncodeToString(data))&nbsp; &nbsp; encryptedData := encrypt(rawKey, data)&nbsp; &nbsp; fmt.Println("encrypted data: ", encryptedData)}func encrypt(rawKey string, plainText []byte) string {&nbsp; &nbsp; salt := []byte("ABCDEFGH") // hardcoded at the moment&nbsp; &nbsp; // Gets key and IV from raw key.&nbsp; &nbsp; key, iv := evp.BytesToKeyAES256CBCMD5([]byte(salt), []byte(rawKey))&nbsp; &nbsp; // Create new AES cipher block&nbsp; &nbsp; block, err := aes.NewCipher(key)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err.Error()&nbsp; &nbsp; }&nbsp; &nbsp; cipherText := make([]byte, len(plainText))&nbsp; &nbsp; // Encrypt.&nbsp; &nbsp; encryptStream := cipher.NewCTR(block, iv)&nbsp; &nbsp; encryptStream.XORKeyStream(cipherText, plainText)&nbsp; &nbsp; ivHex := hex.EncodeToString(iv)&nbsp; &nbsp; encryptedDataHex := hex.EncodeToString([]byte("Salted__")) + hex.EncodeToString(salt) + hex.EncodeToString(cipherText) // 2. Apply the OpenSSL format, hex encode the result&nbsp; &nbsp; return ivHex + ":" + encryptedDataHex // 3. Any value for ivHex can be used here, e.g. "00000000000000000000000000000000"}输出是:padded data:&nbsp; 74686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f670505050505encrypted data:&nbsp; 3a010df5e7985f2d8b0c00e3a096347f:53616c7465645f5f41424344454647486036327f61cf3050fddd6ea76325148c81e170a63b514b8818afbbb894c874c87cc4c865300c7b2d0e0fd82826f3d3c5可以使用遗留代码解密此密文:const decrypt = function (rawKey, encryptedData) {&nbsp; &nbsp; const split = encryptedData.split(':');&nbsp; &nbsp; if (split.length < 2) return '';&nbsp; &nbsp; const reb64 = CryptoJS.enc.Hex.parse(split[1]);&nbsp; &nbsp; const bytes = reb64.toString(CryptoJS.enc.Base64);&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; const hash = CryptoJS.AES.decrypt(bytes, rawKey, {&nbsp; &nbsp; &nbsp; &nbsp; iv: split[0], // This is ignored if the internal PBKDF is used&nbsp; &nbsp; &nbsp; &nbsp; mode: CryptoJS.mode.CTR&nbsp; &nbsp; });&nbsp; &nbsp; const plain = hash.toString(CryptoJS.enc.Utf8);&nbsp; &nbsp; 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>
打开App,查看更多内容
随时随地看视频慕课网APP