Flutter Secure Notes App – Hide Secret Text Inside Image (Steganography)
Demo :
Click Video πππ
FEATURES :
-
Password Protected Notes
-
Secret Text Hidden Inside Image
-
No Visual Difference
-
Flutter Dark UI
-
Beginner Friendly
-
Real Cyber Security Concept
Code :
pubspec.yaml
dependencies:
flutter:
sdk: flutter
image_picker: ^1.0.7
crypto: ^3.0.3
main.dart
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:crypto/crypto.dart';
void main() {
runApp(const SecureStegoApp());
}
class SecureStegoApp extends StatelessWidget {
const SecureStegoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Secure Notes Steganography',
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: const Color(0xFF0B0F1A),
primaryColor: Colors.tealAccent,
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final TextEditingController _textController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
Uint8List? _imageBytes;
String _decodedText = "";
final ImagePicker _picker = ImagePicker();
// π Password hash
String _hashPassword(String pwd) {
return sha256.convert(utf8.encode(pwd)).toString();
}
// π₯ Pick Image
Future<void> pickImage() async {
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
if (image != null) {
_imageBytes = await image.readAsBytes();
setState(() {});
}
}
// π Encode Text into Image (No visible trace)
void encodeText() {
if (_imageBytes == null ||
_textController.text.isEmpty ||
_passwordController.text.isEmpty) {
_showMsg("Select image, text & password");
return;
}
final payload = jsonEncode({
"pwd": _hashPassword(_passwordController.text),
"msg": _textController.text,
});
final encoded = base64Encode(utf8.encode(payload));
// Append encoded data at the end (image remains visually same)
final stegoBytes = Uint8List.fromList(
[..._imageBytes!, ...utf8.encode("::FUZZU::$encoded")],
);
_imageBytes = stegoBytes;
_showMsg("Text hidden successfully π");
setState(() {});
}
// π Decode Text from Image
void decodeText() {
if (_imageBytes == null || _passwordController.text.isEmpty) {
_showMsg("Select image & enter password");
return;
}
final data = utf8.decode(_imageBytes!, allowMalformed: true);
if (!data.contains("::FUZZU::")) {
_showMsg("No hidden data found");
return;
}
final encoded = data.split("::FUZZU::").last.trim();
final decodedJson = utf8.decode(base64Decode(encoded));
final decoded = jsonDecode(decodedJson);
if (decoded["pwd"] == _hashPassword(_passwordController.text)) {
setState(() {
_decodedText = decoded["msg"];
});
} else {
_showMsg("Wrong password ❌");
}
}
void _showMsg(String msg) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(msg)));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("π Secure Notes Steganography"),
centerTitle: true,
backgroundColor: Colors.black,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
children: [
GestureDetector(
onTap: pickImage,
child: Container(
height: 180,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: const Color(0xFF111827),
border: Border.all(color: Colors.tealAccent),
),
child: _imageBytes == null
? const Center(
child: Text(
"Tap to select image",
style: TextStyle(color: Colors.white54),
),
)
: Image.memory(_imageBytes!, fit: BoxFit.cover),
),
),
const SizedBox(height: 16),
TextField(
controller: _passwordController,
obscureText: true,
decoration: const InputDecoration(
labelText: "Password",
border: OutlineInputBorder(),
),
),
const SizedBox(height: 12),
TextField(
controller: _textController,
maxLines: 4,
decoration: const InputDecoration(
labelText: "Secret Text",
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
icon: const Icon(Icons.lock),
label: const Text("Encode"),
onPressed: encodeText,
),
ElevatedButton.icon(
icon: const Icon(Icons.lock_open),
label: const Text("Decode"),
onPressed: decodeText,
),
],
),
const SizedBox(height: 20),
if (_decodedText.isNotEmpty)
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.tealAccent),
),
child: Text(
_decodedText,
style: const TextStyle(color: Colors.greenAccent),
),
),
],
),
),
);
}
}
Comments
Post a Comment