Security: Encryption
Introduction
Magic's encrypter provides a simple, convenient interface for encrypting and decrypting text. All encrypted values are signed using a message authentication code (MAC) so that their underlying value can not be modified or tampered with once encrypted.
Magic uses the AES-256-CBC cipher for all encryption operations.
Configuration
Magic offers two encryption strategies:
- Config-Based: Uses the global
APP_KEYfrom your.envor configuration. Useful for server-side compatibility or shared keys. - Device-Based: Uses a unique, randomly generated key stored securely on the user's device via Vault. This is recommended for storing sensitive user data locally.
Using The Encrypter
Config-Based Encryption
To encrypt a value using your application's global key:
final secret = Crypt.encrypt('my-secret-value');
To decrypt a value:
try {
final value = Crypt.decrypt(secret);
} on MagicDecryptException {
// The value was invalid or tampered with
}
Device-Based Encryption
For local data that should only be accessible on the current device, use device-based encryption. This keys is unique per installation.
// Encrypt
final secret = await Crypt.encryptWithDeviceKey('my-user-token');
// Decrypt
final value = await Crypt.decryptWithDeviceKey(secret);
[!IMPORTANT] Device-based encryption is asynchronous (
Future) because it retrieves the key from secure storage.
Managing Keys
You can check if a device-specific key has already been generated:
if (await Crypt.hasDeviceKey()) {
// Key exists
}
To generate a new device key (Warning: specific to the device encrypter):
// WARNING: This renders previously encrypted data unrecoverable!
await Crypt.generateDeviceKey();
To remove the key entirely:
await Crypt.clearDeviceKey();