I have a golang code which can do AES encryption on the given data and serves it. Below is the code.

crypt.go

func encrypt(key []byte, text string) string {

    plaintext := []byte(text)

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

    ciphertext := make([]byte, aes.BlockSize+len(plaintext))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        panic(err)
    }

    stream := cipher.NewCFBEncrypter(block, iv)
    stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

    return base64.URLEncoding.EncodeToString(ciphertext)
}

func decrypt(key []byte, cryptoText string) string {
    ciphertext, _ := base64.URLEncoding.DecodeString(cryptoText)

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

    if len(ciphertext) < aes.BlockSize {
        panic("ciphertext too short")
    }
    iv := ciphertext[:aes.BlockSize]
    ciphertext = ciphertext[aes.BlockSize:]

    stream := cipher.NewCFBDecrypter(block, iv)
    stream.XORKeyStream(ciphertext, ciphertext)

    return string(ciphertext)
}

I need to handle the same decryption and encryption in Flutter. I tried the below code using flutter encrypt package.

crypt.dart

import 'package:encrypt/encrypt.dart';
String encryption(String plainText) {

     final key = Key.fromBase64(ENCRYPTION_KEY);
     final iv = IV.fromBase64(ENCRYPTION_IV);

     final encrypter = Encrypter(AES(key, mode: AESMode.cfb64, padding: null));
     final encrypted = encrypter.encrypt(plainText, iv: iv);

 return encrypted.base64;   
}

String decryption(String plainText) {

   final key = Key.fromBase64(ENCRYPTION_KEY);
   final iv = IV.fromBase64(ENCRYPTION_IV);

   final encrypter = Encrypter(AES(key, mode: AESMode.cfb64, padding: null));
   final decrypted = encrypter.decrypt(Encrypted.from64(plainText), iv: iv);

  return decrypted;   
 }

But I'm getting error and is not working. Am I missing something? How this can be achieved in flutter end.

Thanks in advance


Solution 1: NotX

At a first glance it seems like your iv (initialization vectors) don't match. When encrypting in Go, you generate it randomly and "place" it in front of the encrypted text, which is fine, and when decrypting in Go, you take it from there.

In Dart (I'm not used to that language though) it seems as you take a static iv from ENCRYPTION_IV. That one won't match a randomly generated one from Go.

Imagine the iv being some kind of clef. It explains how to process the encrypted key. Normally it's not secret, but should be random. So it's fine to generate it with an appropriate randomizer and tell the receiver of the encrypted text about it. A common way is to put it in the front of it - since it's size is fixed in AES to aes.BlockSize (16 bytes), it's clear where the iv ends and the real encrypted text starts.

So, in Dart you should read the first 16 bytes to get the iv from the ciphertext from Go encryption. And while you're at it, I'ld recommend to use a random iv in the Dart encryption method, too.