Secret Storage is an Android library for encrypting and storing local secrets such as account credentials or authentication tokens.
A key-protection strategy can be selected to make use of a user password, AndroidKeyStore, or both.
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
dependencies {
compile 'com.github.cjnosal:secret-storage:v1.0-beta.6'
}
allprojects {
repositories {
flatDir {
dirs 'libs'
}
}
}
dependencies {
compile(name:'secret-storage', ext:'aar')
}
DataStorage keyStorage = new PreferenceStorage(context, "keys");
DataStorage configStorage = new PreferenceStorage(context, "conf");
DataStorage dataStorage = new FileStorage(context.getFilesDir() + "/data");
KeyWrapper keyWrapper = new SignedPasswordKeyWrapper(
context,
DefaultSpecs.getSignedPasswordCryptoConfig(),
configStorage,
keyStorage);
ProtectionSpec dataProtectionSpec = DefaultSpecs.getDefaultDataProtectionSpec();
SecretStorage secretStorage = new new SecretStorage.Builder()
.dataStorage(dataStorage)
.keyWrapper(keyWrapper)
.dataProtectionSpec(dataProtectionSpec)
.build();
DataStorage keyStorage = new PreferenceStorage(context, "keys");
DataStorage configStorage = new PreferenceStorage(context, "conf");
DataStorage dataStorage = new FileStorage(context.getFilesDir() + "/data");
KeyWrapper keyWrapper = new SignedPasswordKeyWrapper(
context,
DefaultSpecs.getPasswordDerivationSpec(),
DefaultSpecs.getPasswordDeviceBindingSpec(context),
DefaultSpecs.getPasswordBasedKeyProtectionSpec(),
configStorage,
keyStorage);
ProtectionSpec dataProtectionSpec = new ProtectionSpec(
DefaultSpecs.getAesGcmCipherSpec(),
DefaultSpecs.getStrongHmacShaIntegritySpec());
SecretStorage secretStorage = new new SecretStorage.Builder()
.dataStorage(dataStorage)
.keyWrapper(keyWrapper)
.dataProtectionSpec(dataProtectionSpec)
.build();
SecretStorage must be unlocked before storing or loading values. Different KeyWrappers require different parameters to unlock.
secretStorage.getEditor().unlock();
If no password has been set:
secretStorage.getEditor().setPassword(password);
If a password has been set:
secretStorage.getEditor().unlock(password);
secretStorage.getEditor().unlock(context, cancellationSignal, listener, handler);
secretStorage.store("mySecret", Encoding.utf8decode("sensitive materials"));
String mySecret = Encoding.utf8encode(secretStorage.load("mySecret"));
byte[] cipherText = secretStorage.encrypt(Encoding.utf8decode("sensitive materials"));
String mySecret = Encoding.utf8encode(secretStorage.decrypt(cipherText));
Generate an AES key in the AndroidKeyStore, requiring fingerprint verification to unlock
Generate an AES key in the AndroidKeyStore
Generate an RSA key pair in the AndroidKeyStore
Derive an encryption key from the user's password using PBKDF2 Bind the derived key to the phone with an RSA key generated in the AndroidKeyStore
Derive an encryption key from the user's password using PBKDF2
(INSECURE) Derive an encryption key from a hardcoded password using PBKDF2
- Root Key Encryption Key (KEK) is generated inside AndroidKeyStore or derived from user password
- Intermediate KEK is generated and retained in memory
- Intermediate KEK is wrapped by the Root KEK and stored in the KeyWrapper's configuration storage
- Root KEK is discarded from memory
- Data Encryption Key (DEK) and Data Signing Key (DSK) are generated
- DEK and DSK are wrapped by the Intermediate KEK and stored in the KeyWrapper's key storage
- User data is encrypted with DEK, signed with DSK, and stored in the SecretStorage's data storage
- DEK and DSK are discarded from memory
- Intermediate KEK is discarded from memory
- Root KEK is derived or AndroidKeyStore reference is loaded
- Intermediate KEK is unwrapped and retained in memory
- Root KEK is discarded from memory
- DEK and DSK are unwrapped
- User data is verified and decrypted
- DEK and DSK are discarded from memory