9
votes

In PHP, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); returns a value of 32, thus apparently saying that AES-256 wants an Initialization Vector of 32 bytes. But this is deceiving, as said in the comments for mcrypt_encrypt:

Also, MCRYPT_RIJNDAEL_256 is not AES-256, it's a different variant of the Rijndael block cipher. If you want AES-256 in mcrypt, you have to use MCRYPT_RIJNDAEL_128 with a 32-byte key. OpenSSL makes it more obvious which mode you are using (i.e. 'aes-128-cbc' vs 'aes-256-ctr').

So of course, with an IV of 32 bytes, the following example does not work in Go (it causes a panic).

score := decodePost(c.PostForm("score"))
iv := decodePost(c.PostForm("iv"))

aesKey := getAESKey()
baseAES, err := aes.NewCipher([]byte(aesKey))
if err != nil {
    c.AbortWithError(500, err)
    return
}
block := cipher.NewCBCDecrypter(baseAES, []byte(iv))
block.CryptBlocks(score, score)

Quoting from the docs of crypto/cipher:

The length of iv must be the same as the Block's block size and must match the iv used to encrypt the data.

(And of course, the AES block size in Go is 16 bytes).

So, finally, how can I decrypt such string in Go?

1
Of course the best solution is to change the Rijndael block size to 128-bits on the other side and eliminate interoperability issues now and in the future.zaph
That would be ideal, but unfortunately I can't do that because I don't have control of the other side (and there is no easy way for me to gain it).morganbaz
Rijndael-256, as quite clearly stated, isn't AES. It's Rijndael. You need an implementation of this for your go code. The reason you need a 32 byte IV is because the block size of Rijndael-256 is 256 bits.Luke Joshua Park

1 Answers

2
votes

Since in Golang you have only built-in standard AES crypto, you need to implement the Rijndael crypto yourself.

I found one here: https://github.com/celso-wo/rijndael256/blob/master/rijndael256.go