• Stars
    star
    145
  • Rank 254,144 (Top 6 %)
  • Language
    Kotlin
  • License
    MIT License
  • Created about 3 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Extensions to store DataStore in EncryptedFile

Encrypted DataStore

Version License

Extensions to store DataStore in EncryptedFile.

⚠️ This tiny library will be maintained until an official solution for DataStore encryption will be released by Google.
Vote for this feature on issue tracker: b/167697691


Installation

Add the dependency:

repositories {
    mavenCentral()
    google()
}

dependencies {
    implementation("io.github.osipxd:security-crypto-datastore:1.0.0-beta01")
    // Or, if you want to use Preferences DataStore:
    implementation("io.github.osipxd:security-crypto-datastore-preferences:1.0.0-beta01")
}

Dependencies:

Usage

To create encrypted DataStore, just use method DataStoreFactory.createEncryptred instead of create and provide EncryptedFile instead of File:

val dataStore = DataStoreFactory.createEncrypted(serializer) {
    EncryptedFile.Builder(
        context.dataStoreFile("filename"),
        context,
        MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
        EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
    ).build()
}
Or even simpler, if you use security-crypto-ktx:1.1.0

⚠️ security-crypto-ktx 1.1.0 is in alpha at the moment this library released, so use it at your own risk

val dataStore = DataStoreFactory.createEncrypted(serializer) {
    EncryptedFile(
        context = context,
        file = context.dataStoreFile("filename"),
        masterKey = MasterKey(context)
    )
}

Similarly, you can create Preferences DataStore:

val dataStore = PreferenceDataStoreFactory.createEncrypted {
    EncryptedFile.Builder(
        // The file should have extension .preferences_pb
        context.dataStoreFile("filename.preferences_pb"),
        context,
        MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
        EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
    ).build()
}
Or even simpler, if you use security-crypto-ktx:1.1.0

⚠️ security-crypto-ktx 1.1.0 is in alpha at the moment this library released, so use it at your own risk

val dataStore = PreferenceDataStoreFactory.createEncrypted {
    EncryptedFile(
        context = context,
        // The file should have extension .preferences_pb
        file = context.dataStoreFile("filename.preferences_pb"),
        masterKey = MasterKey(context)
    )
}

Then you can use the created encrypted DataStore just like simple DataDtore. Look at the DataStore docs for usage guide and examples.

Migration

Migrate from encrypted-datastore to security-crypto-datastore

Change the dependency in build script:

 dependencies {
-    implementation("io.github.osipxd:encrypted-datastore:...")
+    implementation("io.github.osipxd:security-crypto-datastore:...")
 }

New library uses StreamingAead instead of Aead under the hood, so to not lose the previously encrypted data you should specify fallbackAead:

// This AEAD was used to encrypt DataStore previously, we will use it as fallback
val aead = AndroidKeysetManager.Builder()
    .withSharedPref(context, "master_keyset", "master_key_preference")
    .withKeyTemplate(KeyTemplates.get("AES256_GCM"))
    .withMasterKeyUri("android-keystore://master_key")
    .build()
    .keysetHandle
    .getPrimitive(Aead::class.java)

The old code to create DataStore was looking like this:

val dataStore = DataStoreFactory.create(serializer.encrypted(aead)) {
    context.dataStoreFile("filename")
}

The new code will look like this:

val dataStore = DataStoreFactory.createEncrypted(
    serializer,
    encryptionOptions = {
        // Specify fallback Aead to make it possible to decrypt data encrypted with it
        fallbackAead = aead
    }
) {
    EncryptedFile.Builder(
        context.dataStoreFile("filename"), // Keep the same file
        context,
        MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
        EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
    ).build()
}
Or even simpler, if you use security-crypto-ktx:1.1.0

⚠️ security-crypto-ktx 1.1.0 is in alpha at the moment this library released, so use it at your own risk

val dataStore = DataStoreFactory.createEncrypted(
    serializer,
    encryptionOptions = { fallbackAead = aead }
) {
    EncryptedFile(
        context = context,
        file = context.dataStoreFile("filename"), // Keep the same file
        masterKey = MasterKey(context)
    )
}

Thanks

  • Artem Kulakov (Fi5t), for his example of DataStore encryption.
  • Gods of Kotlin, for posibility to hack internal visibility modifier

License

MIT