file_signature 1.0.1 copy "file_signature: ^1.0.1" to clipboard
file_signature: ^1.0.1 copied to clipboard

A pure Dart security utility that validates files by checking Magic Byte signatures. Prevents rename attacks (e.g. .exe as .png) on Mobile, Web, and Desktop.

example/lib/main.dart

import 'package:file_signature/file_signature.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:file_picker/file_picker.dart';

void main() {
  runApp(const MaterialApp(home: FileSignatureDemo()));
}

class FileSignatureDemo extends StatefulWidget {
  const FileSignatureDemo({super.key});

  @override
  State<FileSignatureDemo> createState() => _FileSignatureDemoState();
}

class _FileSignatureDemoState extends State<FileSignatureDemo> {
  String _status = "Pick a file to test security.";
  Color _statusColor = Colors.grey;

  // SCENARIO 1: The "Everyday" Check (Image Picker)
  Future<void> _pickImage() async {
    final picker = ImagePicker();
    final xFile = await picker.pickImage(source: ImageSource.gallery);

    if (xFile == null) return;

    setState(() => _status = "Scanning ${xFile.name}...");

    try {
      // THE GUARD CLAUSE
      // We only allow PNG and JPEG. If you rename .exe to .png, this throws.
      await FileSignature.guard(
        xFile,
        allowed: [FileFormat.png, FileFormat.jpeg],
      );

      // If we reach here, it's safe!
      _updateStatus("✅ Verified Safe Image (PNG/JPG)", Colors.green);
    } on SecurityException catch (e) {
      _updateStatus("⛔ BLOCKED: ${e.message}", Colors.red);
    } catch (e) {
      _updateStatus("Error: $e", Colors.orange);
    }
  }

  // SCENARIO 2: The "Senior" Check (Stream Interceptor)
  Future<void> _pickAnyFile() async {
    // Pick any file (even huge videos)
    FilePickerResult? result = await FilePicker.platform.pickFiles(
      withReadStream: true, // Critical for Web/Large files
    );

    if (result == null) return;

    final file = result.files.first;
    final stream = file.readStream;

    if (stream == null) {
      _updateStatus("Error: Could not read file stream", Colors.orange);
      return;
    }

    setState(() => _status = "Scanning Stream of ${file.name}...");

    try {
      // THE INTERCEPTOR
      // This peeks at the stream without consuming it.
      // We accept PDF and ZIP for this demo.
      final safeStream = FileSignature.guardStream(
        stream,
        allowed: [FileFormat.pdf, FileFormat.zip],
      );

      // Simulate an upload by "draining" the stream
      // In a real app, you would pass 'safeStream' to Dio or http.post
      await safeStream.drain();

      _updateStatus("✅ Stream Verified & Uploaded (PDF/ZIP)", Colors.green);
    } catch (e) {
      _updateStatus("⛔ STREAM KILLED: $e", Colors.red);
    }
  }

  void _updateStatus(String msg, Color color) {
    if (!mounted) return;
    setState(() {
      _status = msg;
      _statusColor = color;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("File Signature Security Demo")),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(20),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(Icons.security, size: 80, color: Colors.blue),
              const SizedBox(height: 20),
              Text(
                _status,
                textAlign: TextAlign.center,
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                  color: _statusColor,
                ),
              ),
              const SizedBox(height: 40),
              ElevatedButton.icon(
                icon: const Icon(Icons.image),
                label: const Text("Test Image Picker (Guard XFile)"),
                onPressed: _pickImage,
              ),
              const SizedBox(height: 10),
              ElevatedButton.icon(
                icon: const Icon(Icons.cloud_upload),
                label: const Text("Test Large File (Guard Stream)"),
                onPressed: _pickAnyFile,
              ),
              const SizedBox(height: 20),
              const Text(
                "Try renaming a .exe to .png and uploading it!",
                style: TextStyle(color: Colors.grey),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
4
likes
160
points
160
downloads

Publisher

verified publisherflutterdude.com

Weekly Downloads

A pure Dart security utility that validates files by checking Magic Byte signatures. Prevents rename attacks (e.g. .exe as .png) on Mobile, Web, and Desktop.

Repository (GitHub)
View/report issues

Topics

#security #files #upload #validation #magic-bytes

Documentation

API reference

License

MIT (license)

Dependencies

cross_file, flutter

More

Packages that depend on file_signature