Daci
Daci

Reputation: 13

Decrypt AES-CBC-256 Mcrypt_RIJNDAEL encrypted in PHP decrypt on GOLang

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.

Upvotes: 0

Views: 1698

Answers (3)

Daci
Daci

Reputation: 13

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

Upvotes: 0

Tschallacka
Tschallacka

Reputation: 28712

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.

Upvotes: 0

Daci
Daci

Reputation: 13

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

Upvotes: 1

Related Questions