Encryption
Introduction
Magic provides encryption services for securing sensitive data. The Crypt facade provides easy-to-use encryption and decryption methods, while the Vault facade provides secure storage using the platform's native secure storage (Keychain on iOS, Keystore on Android).
Configuration
Application Key
Magic's encrypter uses the application key defined in your .env file:
APP_KEY=base64:your-32-character-random-key-here
Generate a new key using the CLI:
magic key:generate
[!WARNING] Never commit your
APP_KEYto version control. Always use environment variables.
Using The Encrypter
Encrypting Values
final encrypted = Crypt.encrypt('my secret data');
// Returns encrypted string
Decrypting Values
final decrypted = Crypt.decrypt(encrypted);
// Returns: 'my secret data'
Encrypting Objects
You can encrypt any JSON-serializable data:
final encrypted = Crypt.encrypt({
'user_id': 1,
'permissions': ['read', 'write'],
'expires': Carbon.now().addHours(1).toIso8601String(),
});
final data = Crypt.decrypt(encrypted);
// Returns the original Map
Error Handling
try {
final decrypted = Crypt.decrypt(invalidString);
} catch (e) {
// Handle decryption failure
print('Failed to decrypt: $e');
}
Vault (Secure Storage)
The Vault facade provides secure storage using the platform's native secure storage mechanisms:
- iOS: Keychain
- Android: Keystore / EncryptedSharedPreferences
- Web: Encrypted localStorage (less secure)
Storing Values
await Vault.put('api_token', 'secret-token-value');
await Vault.put('refresh_token', 'refresh-token-value');
Retrieving Values
final token = await Vault.get('api_token');
if (token != null) {
// Use the token
}
Checking Existence
if (await Vault.has('api_token')) {
// Token exists
}
Deleting Values
await Vault.delete('api_token');
Clearing All Values
await Vault.deleteAll();
Use Cases
Authentication Tokens:
class AuthService {
Future storeTokens(String token, String refreshToken) async {
await Vault.put('auth_token', token);
await Vault.put('refresh_token', refreshToken);
}
Future getToken() async {
return await Vault.get('auth_token');
}
Future clearTokens() async {
await Vault.delete('auth_token');
await Vault.delete('refresh_token');
}
}
Sensitive User Data:
// Store sensitive settings
await Vault.put('pin_code', hashedPin);
await Vault.put('biometric_key', biometricData);
// API keys
await Vault.put('stripe_key', stripePublishableKey);
[!IMPORTANT] Always use
Vaultfor sensitive data like tokens, API keys, and credentials. Never store sensitive data inSharedPreferencesorCache.
Encryption vs Vault
| Feature | Crypt | Vault |
|---|---|---|
| Use Case | Encrypt data for transmission | Store secrets locally |
| Persistence | None (just transforms data) | Persistent secure storage |
| Platform | Cross-platform | Platform-specific secure storage |
| Example | Encrypt payload before API call | Store auth tokens |