0
votes

I try to rewrite some old code made in php5.6 (CodeIgniter) in go, but I'm banging my head with decryption on go. I managed to decode MCRYPT_RIJNDAEL_128 from php to go, where the iv size is 16 characters, but I can't do it on 256 - iv is 32. I don't want to use go_mcrypt because that's strict on libcrypt headers, so I tried using go classic encrypt libs AES cipher with CBC mode, but on 256 it complains about IV length... The php IV has 32 characters not 16 as expected..

The php part works well...

private $CIPHER_KEY = "12345678901234567890123456789012";

    private function Encrypt($toEncrypt=null){
        $iv_size = $this->ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
        $iv = $this->ivKey = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $this->B64IV = base64_encode($iv);
        return base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->CIPHER_KEY, $toEncrypt, MCRYPT_MODE_CBC, $iv));
    }

this is the PHP result:

KEY: 12345678901234567890123456789012
IV: Egu4tSySXluBLi5dcMzHbZHVSOS7jdNwUKUFlZ8dL1w=
ENC: Egu4tSySXluBLi5dcMzHbZHVSOS7jdNwUKUFlZ8dL1yATFjg26/Nav7cWtlJJL3djhUCND6KV8r/JL7owboKFA==
IV Size: 32

IV is included in the encrypted text... (and has 32 chars)

mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); return 32
func main(){
   key := []byte("12345678901234567890123456789012")

   iv,_ := base64.StdEncoding.DecodeString("Egu4tSySXluBLi5dcMzHbZHVSOS7jdNwUKUFlZ8dL1w=")
   encText,_  := base64.StdEncoding.DecodeString("Egu4tSySXluBLi5dcMzHbZHVSOS7jdNwUKUFlZ8dL1yATFjg26/Nav7cWtlJJL3djhUCND6KV8r/JL7owboKFA==")
//   iv := encText[:32] // also tried to get the iv from encoded string


   fmt.Printf("Key Len: %d\nIV  Len: %d\nENC Len: %d\n",len(key),len(iv),len(encText))

    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    if len(encText) < aes.BlockSize {
        panic("cipherText too short")
    }

    cipherText := encText[32:]
    if len(cipherText)%aes.BlockSize != 0 {
        panic("cipherText is not a multiple of the block size")
    }

    mode := cipher.NewCBCDecrypter(block, iv)
    mode.CryptBlocks(cipherText, cipherText)

    cipherText, _ = pkcs7.Unpad(cipherText, aes.BlockSize)

   fmt.Printf("Dec: %s\n",cipherText)

}

Key Len: 32 IV Len: 32 ENC Len: 64 panic: cipher.NewCBCDecrypter: IV length must equal block size

goroutine 1 [running]: crypto/cipher.NewCBCDecrypter(0x10e7c20, 0xc00009a030, 0xc00008a000, 0x20, 0x42, 0x0, 0x0)

IV size is 32 but the block size is 16.

3
OK - I re-re-read the documentation and AES-256 is using only 128 bytes IV (16 chars).. AES is a variant of Rijndael that has a fixed block size of 128 bits, and a key size of 128, 192, or 256 bits. The Rijndael documentation specifiy with block and key sizes multiple of 32 bits, with a minimum of 128 and a maximum of 256 bits, hence the confusion AES is not RIJNDAEL - only a variant. I guess the only solution is to decrypt the sensitive data in php and encrypt it using 128 bytes IV. Anyone know another library - compatible with RIJNDAEL 250 that works with IV of 256 bytes (32 chars)?Daci

3 Answers

0
votes

This works in Linux - for anyone courious how to decode with IV 32 characters

apt install libmcrypt-dev

go get "github.com/tblyler/go-mcrypt"

import (
  "fmt"
  "github.com/tblyler/go-mcrypt"
  "encoding/base64"
)

const (
   KEY = "12345678901234567890123456789012"
   ENC = "Egu4tSySXluBLi5dcMzHbZHVSOS7jdNwUKUFlZ8dL1yATFjg26/Nav7cWtlJJL3djhUCND6KV8r/JL7owboKFA=="
)

func main(){
    encText, _ := base64.StdEncoding.DecodeString(ENC)

    iv := encText[:32]
    toDecrypt := encText[32:]

    fmt.Printf("Key Len: %d\n",len(KEY))
    fmt.Printf("IV  Len: %d\n",len(iv))

    decText, err := mcrypt.Decrypt([]byte(KEY),iv,[]byte(toDecrypt))
    if err != nil { panic(err) }

    fmt.Printf("%s\n",decText)
}
0
votes

I've been playing with a similar issue, when transporting code from php 5.6 to php 7.3. The easiest and most reliable way I have found is just to decrypt all the values with php 5.6 and then recrypt with the new format that works well. It's a one time thing to do when moving over, but it saves a lot of headaches.

0
votes

I just test it from my MacOS, the above code is working from Mohave 10.14.5.

I used MacPorts to install libmcrypt

sudo port install libmcrypt

mkdir mcrypt curl -o mcrypt/mcrypt.go https://raw.githubusercontent.com/tblyler/go-mcrypt/master/mcrypt.go

or copy it from your own src/github.com/tblyler/go-mcrypt to project mcrypt folder

now edit mcrypt.go and add the C flags:

package mcrypt

/*
#cgo LDFLAGS: -L/opt/local/lib -lmcrypt
#cgo CFLAGS: -I/opt/local/include
#include <stdlib.h>
...

modify import from above example to import mcrypt version locally, and run it...

package main

import (
  "fmt"
//"github.com/tblyler/go-mcrypt"
  "./mcrypt"
  "encoding/base64"
)

when running the code it adds a warning about linking

ld: warning: building for macOS, but linking in object file (/var/folders/xz/7ng416ds5611ypt12c96g1_40000gn/T/go-link-754294955/go.o) built for
Key Len: 32
IV  Len: 32
Abra Cadabra