creek

The AI Image Editor of 2030

encryption_service.dart (2038B)


import 'dart:convert';
import 'dart:typed_data';
import 'package:cryptography/cryptography.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

class EncryptionService {
  final _algorithm = AesGcm.with256bits();

  Future<SecretKey> _getSecretKey() async {
    // 1. Fetch key from environment variables
    final base64Key = dotenv.env['SHARED_SECRET_KEY'];

    if (base64Key == null || base64Key.isEmpty) {
      throw Exception("❌ SHARED_SECRET_KEY not found in .env file");
    }

    // 2. Decode the Base64 string to bytes
    final keyBytes = base64Decode(base64Key);
    return SecretKey(keyBytes);
  }

  Future<String> encrypt(String plainText) async {
    final secretKey = await _getSecretKey();

    // 1. Convert text to bytes
    final messageBytes = utf8.encode(plainText);

    // 2. Encrypt (Generates a random nonce automatically)
    final secretBox = await _algorithm.encrypt(
      messageBytes,
      secretKey: secretKey,
    );

    // 3. Pack: Nonce + Ciphertext + Tag (MAC)
    // Note: secretBox.mac.bytes is the Tag
    final combined =
        secretBox.nonce + secretBox.cipherText + secretBox.mac.bytes;

    // 4. Return Base64
    return base64Encode(combined);
  }

  Future<String?> decrypt(String encryptedBase64) async {
    try {
      final secretKey = await _getSecretKey();

      // 1. Decode Base64
      final data = base64Decode(encryptedBase64);

      // 2. Unpack
      // GCM Nonce is 12 bytes
      final nonce = data.sublist(0, 12);
      // Tag (MAC) is last 16 bytes
      final tag = data.sublist(data.length - 16);
      // Ciphertext
      final ciphertext = data.sublist(12, data.length - 16);

      // 3. Reconstruct SecretBox
      final secretBox = SecretBox(ciphertext, nonce: nonce, mac: Mac(tag));

      // 4. Decrypt
      final decryptedBytes = await _algorithm.decrypt(
        secretBox,
        secretKey: secretKey,
      );

      return utf8.decode(decryptedBytes);
    } catch (e) {
      print("Decryption error: $e");
      return null;
    }
  }
}