skip to Main Content

I want to apply AES/GCM/NoPadding Encryption and Decryption in my Flutter Application

The Use-case : i will encrypt some String and send it to server and server will decrypt and process it and will send me updated encrypted data and again i will decrypt it to process it.

And i have tried exploring cryptography, cryptography_flutter, encrypt and pointycastle.

but not found any clear documentation where i can apply AES/GCM/NoPadding for encryption.
And i cannot apply AES/CBC/PKCS5PADDING or AES/CBC/PKCS7PADDING as the point stucks under APPSEC.

Can anyone please help how can i perform AES/GCM/NoPadding Encryption and Decryption in Flutter/Dart.

Thanks in advance.

2

Answers


  1. This is a simple string encryption (and decryption) using PointyCastle in Dart/Flutter. As commented by @Topaco, you should consider using a secure key derivation like PBKDF2:

    import 'dart:convert';
    import 'dart:math';
    import 'dart:typed_data';
    import "package:pointycastle/export.dart";
    
    main() {
    /* add in pubspec.yaml:
    dependencies:
      pointycastle: ^3.1.1
     */
    
      printC('AES GCM 256 String encryption with random key');
      final plaintext = 'The quick brown fox jumps over the lazy dog';
      printC('plaintext: ' + plaintext);
    
      // generate random key
      var encryptionKey = generateRandomAesKey();
      var encryptionKeyBase64 = base64Encoding(encryptionKey);
      printC('encryptionKey (Base64): ' + encryptionKeyBase64);
    
      // encryption
      printC('n* * * Encryption * * *');
      String ciphertextBase64 = aesGcmEncryptionToBase64(encryptionKey, plaintext);
      printC('ciphertext (Base64): ' + ciphertextBase64);
      printC('output is (Base64) nonce : (Base64) ciphertext : (Base64) gcmTag');
    
      printC('n* * * Decryption * * *');
      var ciphertextDecryptionBase64 = ciphertextBase64;
      printC('ciphertext (Base64): ' + ciphertextDecryptionBase64);
      printC('input is (Base64) nonce : (Base64) ciphertext : (Base64) gcmTag');
      var decryptedtext = aesGcmDecryptionFromBase64(encryptionKey, ciphertextDecryptionBase64);
      printC('plaintext:  ' + decryptedtext);
    }
    
    String aesGcmEncryptionToBase64(Uint8List key, String plaintext) {
      var plaintextUint8 = createUint8ListFromString(plaintext);
      final nonce = generateRandomNonce();
      final cipher = GCMBlockCipher(AESFastEngine());
      var aeadParameters = AEADParameters(KeyParameter(key), 128, nonce, Uint8List(0));
      cipher.init(true, aeadParameters);
      var ciphertextWithTag = cipher.process(plaintextUint8);
      var ciphertextWithTagLength = ciphertextWithTag.lengthInBytes;
      var ciphertextLength = ciphertextWithTagLength - 16; // 16 bytes = 128 bit tag length
      var ciphertext = Uint8List.sublistView(ciphertextWithTag, 0, ciphertextLength);
      var gcmTag = Uint8List.sublistView(ciphertextWithTag, ciphertextLength, ciphertextWithTagLength);
      final nonceBase64 = base64.encode(nonce);
      final ciphertextBase64 = base64.encode(ciphertext);
      final gcmTagBase64 = base64.encode(gcmTag);
      return nonceBase64 + ':' + ciphertextBase64 + ':' + gcmTagBase64;
    }
    
    String aesGcmDecryptionFromBase64(Uint8List key, String data) {
      var parts = data.split(':');
      var nonce = base64.decode(parts[0]);
      var ciphertext = base64.decode(parts[1]);
      var gcmTag = base64.decode(parts[2]);
      var bb = BytesBuilder();
      bb.add(ciphertext);
      bb.add(gcmTag);
      var ciphertextWithTag = bb.toBytes();
      final cipher = GCMBlockCipher(AESFastEngine());
      var aeadParameters = AEADParameters(KeyParameter(key), 128, nonce, Uint8List(0));
      cipher.init(false, aeadParameters);
      return new String.fromCharCodes(cipher.process(ciphertextWithTag));
    }
    
    Uint8List generateRandomAesKey() {
      final _sGen = Random.secure();
      final _seed =
      Uint8List.fromList(List.generate(32, (n) => _sGen.nextInt(255)));
      SecureRandom sec = SecureRandom("Fortuna")..seed(KeyParameter(_seed));
      return sec.nextBytes(32);
    }
    
    Uint8List generateRandomNonce() {
      final _sGen = Random.secure();
      final _seed =
      Uint8List.fromList(List.generate(32, (n) => _sGen.nextInt(255)));
      SecureRandom sec = SecureRandom("Fortuna")..seed(KeyParameter(_seed));
      return sec.nextBytes(12);
    }
    
    Uint8List createUint8ListFromString(String s) {
      var ret = new Uint8List(s.length);
      for (var i = 0; i < s.length; i++) {
        ret[i] = s.codeUnitAt(i);
      }
      return ret;
    }
    
    String base64Encoding(Uint8List input) {
      return base64.encode(input);
    }
    
    Uint8List base64Decoding(String input) {
      return base64.decode(input);
    }
    
    void printC(String newString) {
      // for compatibility reasons to FlutterEmptyConsole
      print(newString);
    }
    
    Login or Signup to reply.
  2. AES/GCM/NoPadding is a particular encryption mode for AES that not only encrypts data but also guarantees the message’s integrity and validity. It is frequently used for secure data transfer. Nevertheless, AES/GCM/NoPadding are not natively supported by the default dart: crypto library. The Pointycastle library can be used to perform encryption and decryption using AES/GCM/NoPadding. The cryptographic features offered by this library are created specifically for Dart programming.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search