Reputation: 13
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
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
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
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