Skip to content

Instantly share code, notes, and snippets.

@ffkev
Created May 20, 2024 03:30
Show Gist options
  • Save ffkev/6d72e2220720d714eba15af4264bcec1 to your computer and use it in GitHub Desktop.
Save ffkev/6d72e2220720d714eba15af4264bcec1 to your computer and use it in GitHub Desktop.
AES gmc Encryption / Decryption logic in Flutter
import 'dart:convert';
import 'dart:typed_data';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(EncryptionApp());
}
class EncryptionApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Encryption App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: EncryptionPage(),
);
}
}
class EncryptionPage extends StatefulWidget {
@override
_EncryptionPageState createState() => _EncryptionPageState();
}
class _EncryptionPageState extends State<EncryptionPage> {
final TextEditingController _contentController = TextEditingController();
final TextEditingController _aesKeyController = TextEditingController();
final TextEditingController _encryptedDataController = TextEditingController();
final TextEditingController _decryptionKeyController = TextEditingController();
String _encryptedData = '';
String _decryptedData = '';
Future<void> _encrypt() async {
final content = _contentController.text;
final aesKey = _aesKeyController.text;
if (content.isEmpty || aesKey.isEmpty) {
setState(() {
_encryptedData = 'Content and AES key cannot be empty';
});
return;
}
try {
final key = encrypt.Key(Uint8List.fromList(base64Decode(aesKey)));
final iv = encrypt.IV.fromSecureRandom(12); // AES-GCM typically uses a 12-byte IV
final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.gcm));
final encrypted = encrypter.encrypt(content, iv: iv);
final gcm = encrypted.bytes;
// Split ciphertext and tag
final ciphertext = gcm.sublist(0, gcm.length - 16);
final tag = gcm.sublist(gcm.length - 16);
final ciphertextb64 = base64Encode(ciphertext);
final nonceb64 = base64Encode(iv.bytes);
final tagb64 = base64Encode(tag);
final finalData = '$ciphertextb64~$nonceb64~$tagb64';
setState(() {
_encryptedData = finalData;
});
} catch (e) {
setState(() {
_encryptedData = 'Encryption error: $e';
});
}
}
Future<void> _decrypt() async {
final encryptedData = _encryptedDataController.text;
final aesKey = _decryptionKeyController.text;
if (encryptedData.isEmpty || aesKey.isEmpty) {
setState(() {
_decryptedData = 'Encrypted data and AES key cannot be empty';
});
return;
}
try {
final key = encrypt.Key(Uint8List.fromList(base64Decode(aesKey)));
final parts = encryptedData.split('~');
final ciphertext = base64Decode(parts[0]);
final nonce = base64Decode(parts[1]);
final tag = base64Decode(parts[2]);
final combinedData = Uint8List(ciphertext.length + tag.length)
..setAll(0, ciphertext)
..setAll(ciphertext.length, tag);
final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.gcm));
final iv = encrypt.IV(nonce);
final decrypted = encrypter.decrypt64(base64Encode(combinedData), iv: iv);
setState(() {
_decryptedData = decrypted;
});
} catch (e) {
setState(() {
_decryptedData = 'Decryption error: $e';
});
}
}
void _copyToClipboard(String text) {
Clipboard.setData(ClipboardData(text: text));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Copied to clipboard')),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Encryption App'),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _contentController,
decoration: InputDecoration(labelText: 'Content to Encrypt'),
),
TextField(
controller: _aesKeyController,
decoration: InputDecoration(labelText: 'AES Key for Encryption'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _encrypt,
child: Text('Encrypt'),
),
SizedBox(height: 20),
SelectableText(
'Encrypted Data: $_encryptedData',
style: TextStyle(fontSize: 16),
),
ElevatedButton(
onPressed: () => _copyToClipboard(_encryptedData),
child: Text('Copy Encrypted Data'),
),
Divider(),
TextField(
controller: _encryptedDataController,
decoration: InputDecoration(labelText: 'Encrypted Data'),
),
TextField(
controller: _decryptionKeyController,
decoration: InputDecoration(labelText: 'AES Key for Decryption'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _decrypt,
child: Text('Decrypt'),
),
SizedBox(height: 20),
SelectableText(
'Decrypted Data: $_decryptedData',
style: TextStyle(fontSize: 16),
),
ElevatedButton(
onPressed: () => _copyToClipboard(_decryptedData),
child: Text('Copy Decrypted Data'),
),
],
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment