A security and privacy-first Flutter mobile application for OneTimeSecret, enabling secure sharing of sensitive information through self-destructing, one-time-use secrets.
OneTimeSecret Flutter is a mobile application that allows users to create, share, and reveal secrets that automatically self-destruct after being read. Built with security-first principles, it implements industry-standard encryption, secure storage, and runtime protection mechanisms.
- Create Secrets: Share sensitive information with time-to-live (TTL) expiration
- Passphrase Protection: Optional passphrase encryption for additional security
- QR Code Sharing: Generate and scan QR codes for easy secret sharing
- Self-Destructing Links: Secrets are automatically destroyed after being viewed once
- Secure Storage: Platform-specific encrypted storage (Keychain/EncryptedSharedPreferences)
- Certificate Pinning: Enhanced network security for API communications
- Runtime Protection: RASP (Runtime Application Self-Protection) enabled
- Clean Architecture: Maintainable, testable codebase with clear separation of concerns
This application follows Clean Architecture principles with three distinct layers:
┌─────────────────────────────────────────┐
│ Presentation Layer │
│ (BLoC, Pages, Widgets) │
├─────────────────────────────────────────┤
│ Domain Layer │
│ (Entities, Use Cases, Repositories) │
├─────────────────────────────────────────┤
│ Data Layer │
│ (API Client, Models, Repositories) │
└─────────────────────────────────────────┘
lib/
├── config/ # Application configuration
│ ├── dependency_injection.dart
│ ├── router.dart
│ └── theme.dart
├── core/ # Core utilities and shared code
│ ├── constants/ # App and API constants
│ ├── errors/ # Error handling (failures, exceptions)
│ ├── network/ # Network utilities (DIO client)
│ ├── security/ # Security utilities (encryption, RASP)
│ └── storage/ # Secure storage service
├── data/ # Data layer
│ ├── datasources/ # API clients (Retrofit)
│ ├── models/ # Data models (DTOs)
│ └── repositories/ # Repository implementations
├── domain/ # Domain layer
│ ├── entities/ # Business entities
│ ├── repositories/ # Repository interfaces
│ └── usecases/ # Business logic use cases
└── presentation/ # Presentation layer
├── blocs/ # State management (BLoC)
├── pages/ # UI screens
└── widgets/ # Reusable widgets
- Flutter: 3.38+ (Impeller rendering engine)
- Dart: 3.10+
- State Management: BLoC (flutter_bloc)
- Dependency Injection: get_it + injectable
- HTTP Client: Dio
- REST Client: Retrofit
- Certificate Pinning: http_certificate_pinning
- Connectivity: connectivity_plus
- Secure Storage: flutter_secure_storage (Keychain/EncryptedSharedPreferences)
- Encryption: crypto, encrypt, pointycastle
- RASP: freerasp (Runtime Application Self-Protection)
- Fonts: Google Fonts (Inter)
- QR Codes: qr_flutter, mobile_scanner
- Sharing: share_plus
- Icons: Cupertino Icons
- Unit Testing: flutter_test, mockito
- BLoC Testing: bloc_test
- Integration Testing: integration_test
- Flutter SDK 3.38.0 or higher
- Dart SDK 3.10.0 or higher
- Android Studio (for Android development)
- Xcode 15.0+ (for iOS/iPadOS development, macOS only)
- Clone the repository
git clone <repository-url>
cd onetimesecret_flutter- Install dependencies
flutter pub get- Generate required files
flutter pub run build_runner build --delete-conflicting-outputs- Run the app
# Debug mode
flutter run
# Specific device
flutter run -d <device-id>
# Release mode
flutter run --releaseFor detailed build and deployment instructions, see BUILD.md.
# Debug APK
flutter build apk --debug
# Release APK
flutter build apk --release --obfuscate --split-debug-info=build/app/outputs/symbols
# Release App Bundle (Play Store)
flutter build appbundle --release --obfuscate --split-debug-info=build/app/outputs/symbols# Debug build
flutter build ios --debug --no-codesign
# Release build
flutter build ios --release --obfuscate --split-debug-info=build/ios/outputs/symbols# All tests
flutter test
# Unit tests only
flutter test test/unit/
# Widget tests only
flutter test test/widget/
# Integration tests
flutter test integration_test/
# With coverage
flutter test --coverage# Generate coverage report
flutter test --coverage
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.htmlThis application integrates with the OneTimeSecret API v2. Key endpoints:
POST /api/v2/share- Create a new secretPOST /api/v2/secret/:key- Reveal a secret (consumes it)POST /api/v2/private/:key/burn- Manually destroy a secretGET /api/v2/private/recent- Get recent secrets (authenticated)GET /api/v2/status- API health check
The API supports two modes:
- Anonymous: Limited functionality, no authentication required
- Authenticated: Full access using Basic Auth (username:apikey)
Get API credentials at onetimesecret.com/account
- iOS: Keychain Services with biometric protection
- Android: EncryptedSharedPreferences with AES-256 encryption
SSL/TLS certificate validation to prevent man-in-the-middle attacks.
- Android: ProGuard rules configured
- iOS: Symbol stripping and bitcode enabled
Detects and responds to:
- Root/Jailbreak detection
- Debug mode detection
- Hooking framework detection
- Emulator/Simulator detection
- App integrity checks
- HTTPS enforced for all communications
- No cleartext traffic allowed
- TLS 1.2+ required
- Certificate validation with pinning
Update in lib/core/constants/app_constants.dart:
static const String baseUrl = 'https://onetimesecret.com';Add certificate fingerprints in lib/core/constants/app_constants.dart:
static const List<String> allowedSHA256Fingerprints = [
'sha256/YOUR_CERTIFICATE_FINGERPRINT',
];Update in lib/core/security/rasp_config.dart:
// Android signing certificate
signingCertHashes: ['YOUR_CERT_HASH'],
// iOS Team ID
teamId: 'YOUR_TEAM_ID',The project uses code generation for:
- JSON Serialization:
json_serializable - API Client:
retrofit_generator - Dependency Injection:
injectable_generator - Test Mocks:
mockito
Run after modifying annotated classes:
flutter pub run build_runner build --delete-conflicting-outputs
# Watch mode for continuous generation
flutter pub run build_runner watch --delete-conflicting-outputsUses BLoC pattern for predictable state management:
AuthBloc: Authentication and user sessionSecretBloc: Secret creation, revelation, and management
Uses get_it with injectable for clean dependency injection:
// Register dependencies
await configureDependencies();
// Access anywhere
final authBloc = getIt<AuthBloc>();Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Follow Flutter style guide and best practices
- Write tests for new features
- Ensure all tests pass (
flutter test) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Effective Dart
- Use
flutter analyzeto check for issues - Format code with
flutter format - Write meaningful commit messages
- Biometric authentication
- Dark mode theme customization
- Offline secret creation with sync
- Secret expiration notifications
- Multiple API endpoint support
- Secret templates
- Batch secret operations
- Export/backup functionality
- Multi-language support (i18n)
This project is licensed under the MIT License - see the LICENSE file for details.
- OneTimeSecret for the excellent secret-sharing service
- Flutter team for the amazing framework
- Open-source community for security best practices and libraries
- Documentation: See BUILD.md for detailed build instructions
- Issues: Report bugs via GitHub Issues
- Security: Report security vulnerabilities privately to the maintainers
This application is a client implementation for OneTimeSecret. Use at your own risk. Always verify the security requirements for your specific use case.
Built with ❤️ using Flutter
For questions or support, please open an issue on GitHub.