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

Cha*_*cha 1 encryption cryptography aes go node.js

我使用以下 Node JS 代码加密了一些 JSON 文本:-

var algorithm = 'aes-256-ctr';
var crypto = require('crypto');

var password = "6A80FD8D38D579D1090F6CDB62C729311781E4BA31CD7D804BD7BF5AEC3BFC2D"

var typedRequest = {"abc":"cde"}

var cipher = crypto.createCipher(algorithm, password);
var hashRequest = cipher.update(JSON.stringify(typedRequest),
    'utf8', 'hex');
hashRequest += cipher.final('hex');
Run Code Online (Sandbox Code Playgroud)

现在,我想在 Golang 中解密这个加密文本。但我无法找到任何方法来做到这一点,因为在 Golang 中 AES 256 CTR 的几乎所有解密逻辑示例中,我发现解密时总是需要 IV,但我在 Node JS 中没有使用相同的方法。我已经用 Golang 写了一些东西,但它现在无法正确解密并给出错误:-

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/hex"
    "fmt"

)

func main() {

    encKey := "6A80FD8D38D579D1090F6CDB62C729311781E4BA31CD7D804BD7BF5AEC3BFC2D"
    cipherText := "746c17cd10f8f86646f843ac2a"

    encKeyDecoded, err := hex.DecodeString(encKey)
    if err != nil {
        panic(err)
    }
    cipherTextDecoded, err := hex.DecodeString(cipherText)
    if err != nil {
        panic(err)
    }

    iv := cipherTextDecoded[:aes.BlockSize]

    block, err := aes.NewCipher([]byte(encKeyDecoded))
    if err != nil {
        panic(err)
    }

    cipherTextBytes := []byte(cipherTextDecoded)

    plaintext := make([]byte, len(cipherTextBytes) - aes.BlockSize)
    stream := cipher.NewCTR(block, iv)
    stream.XORKeyStream(plaintext, cipherTextBytes[aes.BlockSize:])

    fmt.Println(string(plaintext))
}
Run Code Online (Sandbox Code Playgroud)

非常感谢任何获得正确 Golang 代码的帮助。谢谢

=======================================

现在,在采纳答案的建议后,我已更新为以下内容:-

这是我的节点 js 代码:-

var crypto = require('crypto'),
  algorithm = 'aes-256-ctr',
  password = '6A80FD8D38D579D1090F6CDB62CA34CA',
  // do not use a global iv for production, 
  // generate a new one for each encryption
  iv = '79b67e539e7fcadf'

var typedRequest = {"abc":"cde"}

var cipher = crypto.createCipheriv(algorithm, password, iv);
var hashRequest = cipher.update(JSON.stringify(typedRequest),
    'utf8', 'hex');
hashRequest += iv.toString('hex') + cipher.final('hex');
Run Code Online (Sandbox Code Playgroud)

这是我的 Go 代码:-

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/hex"
    "fmt"

)

func main() {

    encKey := "6A80FD8D38D579D1090F6CDB62CA34CA"
    cipherText := "af7d1eb42107549a7e3adbce1a79b67e539e7fcadf" // Got from above

    encKeyDecoded, err := hex.DecodeString(encKey)
    if err != nil {
        panic(err)
    }
    cipherTextDecoded, err := hex.DecodeString(cipherText)
    if err != nil {
        panic(err)
    }

    block, err := aes.NewCipher([]byte(encKeyDecoded))
    if err != nil {
        panic(err)
    }

    iv := cipherTextDecoded[:aes.BlockSize]
    cipherTextBytes := []byte(cipherTextDecoded)

    plaintext := make([]byte, len(cipherTextBytes) - aes.BlockSize)
    stream := cipher.NewCTR(block, iv)
    stream.XORKeyStream(plaintext, cipherTextBytes[aes.BlockSize:])

    fmt.Println(string(plaintext))
}
Run Code Online (Sandbox Code Playgroud)

现在,我得到了解密形式的完全不同的东西。

Luk*_*ark 5

这是你的 NodeJS 代码不正确。CTR 模式需要 IV,调用crypto.createCipher对于 CTR 模式来说是未定义的行为。

根据Crypto的 NodeJS 文档,您应该使用crypto.createCipheriv. 您的 Golang 代码尝试从明文开头检索此 IV,因此您需要将其放置在 NodeJS 代码中。

每个加密操作的 IV 应该是唯一的,建议使用 CSPRNG 来实现此目的。