Home > OS >  Port go AES Encrypt function to node.js
Port go AES Encrypt function to node.js

Time:12-23

Im trying to port a go program (https://github.com/McKael/samtv) that can control samsung TVs via the "SmartView" API to node.js

In the program is a "AES Encrypt" function that i have trouble with porting to node.

func (s *SmartViewSession) aesEncrypt(plaindata []byte) ([]byte, error) {
    //logrus.Debugf("aesEncrypt(%#v) : '%s'", plaindata, string(plaindata))
    //logrus.Debugf("session ID:  %d", s.sessionID)
    //logrus.Debugf("session key: '%x'\n  %v", string(s.sessionKey), s.sessionKey)

    // Create cipher block
    block, err := aes.NewCipher(s.sessionKey)
    if err != nil {
        return nil, err
    }

    bs := block.BlockSize()
    //logrus.Debugf("block size: %d", bs)

    // Add padding
    padding := bs - len(plaindata)%bs
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    //logrus.Debugf("padding: %d byte(s)", padding)
    plaindata = append(plaindata, padtext...)

    // Encrypt
    ciphertext := make([]byte, len(plaindata))
    for cipherrange := ciphertext; len(plaindata) > 0; {
        block.Encrypt(cipherrange, plaindata[:bs])
        plaindata = plaindata[bs:]
        cipherrange = cipherrange[bs:]
    }

    //logrus.Debugf("ciphertext: %#v", ciphertext)
    return ciphertext, nil
}

The problem im facing right now is, i dont know what algorythim is used, or where the "initial vector" is coming from i need to specify in my node.js function:

const SESSION_KEY = "59e8ca4b09f2a19ab5421cf55d604c7c";

var aesEncrypt = ((val, algo = "aes-256-cbc") => {
    let cipher = crypto.createCipheriv(algo, SESSION_KEY, IV);
    let encrypted = cipher.update(val, 'utf8', 'base64');
    encrypted  = cipher.final('base64');
    return encrypted;
});

Sould i use crypto.createCipher(...) instead? But its deprecated and have also the feeling that the padding stuff is important.

I have absolutely no clue about encryption. Any hint is welcome.

NOTE: In the go function, s.sessionKey is the same value as in node.js the SESSION_KEY = "59e8ca4b09f2a19ab5421cf55d604c7c"

CodePudding user response:

The Go code applies AES in ECB mode with PKCS#7 padding. The AES variant is implicitly derived from the keysize, e.g. AES-128 for a 16 bytes key. The ciphertext is returned as []byte.

In the NodeJS code, the AES variant is explicitly specified, along with the mode, e.g. aes-128-ecb. The ECB mode does not apply an IV, so it must be specified as null in createCipheriv(). As padding PKCS#7 (default) is used. The ciphertext can be returned as Buffer, which is closest to []byte.

The posted key 59e8ca4b09f2a19ab5421cf55d604c7c looks like a hex encoded key, which is hex decoded 16 bytes large and thus corresponds to AES-128. The hex decoding can be achieved in Go with the encoding/hex package, e.g. with hex.DecodeString("59e8ca4b09f2a19ab5421cf55d604c7c").

Example for a NodeJS code that uses AES-128 (16 bytes key) in ECB mode and PKCS#7 padding:

var crypto = require('crypto');

const SESSION_KEY = Buffer.from("59e8ca4b09f2a19ab5421cf55d604c7c", "hex");

var aesEncrypt = ((val, algo = "aes-128-ecb") => {
    let cipher = crypto.createCipheriv(algo, SESSION_KEY, null);
    return Buffer.concat([cipher.update(val, 'utf8'), cipher.final()]);
});

var ciphertext = aesEncrypt("The quick brown fox jumps over the lazy dog");
console.log(ciphertext.toString('base64')); // T/uQforseVFkY93mqwpwCGVVnEFDTT5Gle8a8XUxCfOXCfYUo3uCJ/nwzCIJ9xqf

The Go code gives the same result using the same key (hex decoded) and plaintext and with Base64 encoding of the ciphertext.

For completeness: The key could also be UTF-8 encoded and would then result in a 32 bytes key, e.g. with key := []byte("59e8ca4b09f2a19ab5421cf55d604c7c") in the Go code and const SESSION_KEY = Buffer.from("59e8ca4b09f2a19ab5421cf55d604c7c", "utf-8") in the NodeJS code. In the NodeJS code, additionally aes-256-ecb must be applied. Ultimately, the key specification must provide information about which encoding to use.


Note that the ECB mode is insecure. Nowadays, authenticated encryption is usually used, e.g. via GCM mode.

  • Related