1

I have encrypted some JSON Text using following Node JS code:-

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');

And now, I wanted to decrypt this encryptedText in Golang. But I am not able to found any way to do this, since in almost all decryption logic examples of AES 256 CTR in Golang, I found it always requires IV while decrypting but I have not use the same in Node JS. I have written something in Golang but its not decrypting correctly and giving error for now:-

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))
}

Any help in getting the correct Golang code is highly appreciated. Thanks

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

Now, I have updated to following after taking suggestion from Answer:-

This is my node js code:-

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');

This is my Go code:-

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))
}

Now, I am getting something completely different in decrypted form.

8
  • What does "I got require IV but I have not use the same in Node JS" mean? Commented Dec 8, 2017 at 19:27
  • Updated the question. Thanks for noticing. Commented Dec 8, 2017 at 19:33
  • For CTR mode an initial counter is required, many times supplied as an IV. It could be that Node JS internally creates a counter and it is returned in some manor or added to the encrypted data in the same manor an IV is many time add as a prefix to the encrypted data. Tjere are other questions such as do the encryption functions expect a hexadecimal string as the key? Commented Dec 8, 2017 at 19:35
  • What is the value of JSON.stringify(typedRequest)? Commented Dec 8, 2017 at 19:39
  • The documentation here explains the process: nodejs.org/api/…. You shouldn't be using a ctr mode here at all, and probably should use createCipheriv Commented Dec 8, 2017 at 19:39

1 Answer 1

5

It is your NodeJS code that is incorrect. CTR mode requires an IV, calling crypto.createCipher is undefined behavior for CTR mode.

As per the NodeJS docs for Crypto, you should be using crypto.createCipheriv. Your Golang code attempts to retrieve this IV from the start of the plaintext, so you'll need to place it there in your NodeJS code.

The IV should be unique for each encryption operation, using a CSPRNG is the recommended way to do this.

Sign up to request clarification or add additional context in comments.

3 Comments

Can I keep the algorithm same as aes-256-ctr? And what would be the length of iv?
@Chacha Yes, and IV length is always the same as the block size, so 128 bits for AES.
I have updated the question. If possible, can you please help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.