为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
噜噜哒 2022-11-23 20:06:38

我必须使用 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):]

}



查看完整描述

1 回答

?
慕侠2389804

TA贡献1460条经验 获得超6个赞

代码基本没问题,只有几个小问题:

  1. CryptoJS 不会自动禁用流密码模式(如 CTR)的默认 PKCS7 填充。因此,必须在 Go 代码中应用 PKCS7 填充。

  2. 由于CryptoJS代码使用内部的PBKDF,所以解密需要OpenSSL格式(即Salted__的ASCII编码后跟8字节salt和实际密文),十六进制编码。因此 Go 代码必须相应地格式化和编码数据。

  3. 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>


查看完整回答
反对 回复 2022-11-23

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信