flutterdartaescryptojspointycastle

aes encryption getting issue with when trying to encrypt username , Bad state: AES engine not initialised


below here Aes encryption code logic.

static String encryptAESGCM(String plaintext, String key) {
    try {
      final keyBytes = Uint8List.fromList(utf8.encode(key));
      final nonce = generateNonce();

      final cipher = GCMBlockCipher(AESEngine());
      final params = AEADParameters(KeyParameter(keyBytes), 128, nonce, Uint8List(0));
      cipher.init(true, params); // Initialize for encryption

      final plaintextBytes = utf8.encode(plaintext);
      final ciphertextBytes = cipher.process(Uint8List.fromList(plaintextBytes)); // Process all data at once

      return base64.encode(ciphertextBytes); // Base64 encode for transmission
    } catch (error) {
      // Handle encryption errors gracefully
      print("Encryption error: $error");
      return ""; // Or return a suitable error message
    }
  }

static Uint8List generateNonce() {
    final random = FortunaRandom(); // Or any other CSPRNG
    return random.nextBytes(12); // 12 bytes for AES-GCM
  }

here in this function generateNonce() , i am getting error Bad state: AES engine not initialised what's the issue in this code

i am trying to encrypt my username & password using aes encryption, but i am getting this issue Bad state: AES engine not initialised. what is the error in my code i am new to this please help.


Solution

  • For cryptographically secure random numbers, a cryptographically secure pseudo random number generator (CSPRNG) is required.

    Random.secure() from the dart.math library provides such a CSPRNG which automatically uses a cryptographically secure source (if none is available, an exception is thrown).
    But be careful not to confuse this with Random(), which only provides a PRNG that is not cryptographically secure.

    Alternatively, there is the class SecureRandom from PointyCastle, for which FortunaRandom is a possible implementation of the Fortuna algorithm (among other algorithms), which must be explicitly seeded with some entropy.
    This is what you use, but you forget the seed, which leads to the exception. Typically the seed is generated with Random.secure().
    One advantage of SecureRandom over (the poorly specified) Random.secure() is that it is more transparent and can be used more flexibly, as algorithm and seed can be controlled.

    Below are sample implementations for all three cases:

    import 'dart:math';
    import 'dart:typed_data';
    import 'package:pointycastle/export.dart';
    
    ...
    
    // FortunaRandom()     cryptographically secure
    SecureRandom secureRandom = getSecureRandom();
    Uint8List data1 = secureRandom.nextBytes(12);
    
    // Random.secure()     cryptographically secure
    Uint8List data2 = generateSecureRandomData(12);
    
    // Random()            not cryptographically secure !!!
    Uint8List data3 = generateNonSecureRandomData(12);
    
    ...
    
    SecureRandom getSecureRandom() {
      List<int> seed = List<int>.generate(32, (_) => Random.secure().nextInt(256));
      return FortunaRandom()..seed(KeyParameter(Uint8List.fromList(seed))); // cryptographically secure
    }
    
    Uint8List generateSecureRandomData(size) {
      return Uint8List.fromList(List<int>.generate(size, (_) => Random.secure().nextInt(256))); // cryptographically secure
    }
    
    Uint8List generateNonSecureRandomData(size) {
      return Uint8List.fromList(List<int>.generate(size, (_) => Random().nextInt(256))); // not cryptographically secure!!!
    }