Last active
April 14, 2022 15:04
-
-
Save shafty023/a223f229ef232818c2e7cfab62c5b1f5 to your computer and use it in GitHub Desktop.
Encrypt the key and store it
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun persistRawKey(userPasscode: CharArray) { | |
val storable = toStorable(rawByteKey, userPasscode) | |
// Implementation explained in next step | |
saveToPrefs(storable) | |
} | |
/** | |
* Returns a [Storable] instance with the db key encrypted using PBE. | |
* | |
* @param rawDbKey the raw database key | |
* @param userPasscode the user's passcode | |
* @return storable instance | |
*/ | |
fun toStorable(rawDbKey: ByteArray, userPasscode: CharArray): Storable { | |
// Generate a random 8 byte salt | |
val salt = ByteArray(8).apply { | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
SecureRandom.getInstanceStrong().nextBytes(this) | |
} else { | |
SecureRandom().nextBytes(this) | |
} | |
} | |
val secret: SecretKey = generateSecretKey(userPasscode, salt) | |
// Now encrypt the database key with PBE | |
val cipher: Cipher = Cipher.getInstance("AES/GCM/NoPadding") | |
cipher.init(Cipher.ENCRYPT_MODE, secret) | |
val params: AlgorithmParameters = cipher.parameters | |
val iv: ByteArray = params.getParameterSpec(IvParameterSpec::class.java).iv | |
val ciphertext: ByteArray = cipher.doFinal(rawDbKey) | |
// Return the IV and CipherText which can be stored to disk | |
return Storable( | |
Base64.encodeToString(iv, Base64.DEFAULT), | |
Base64.encodeToString(ciphertext, Base64.DEFAULT), | |
Base64.encodeToString(salt, Base64.DEFAULT) | |
) | |
} | |
private fun generateSecretKey(passcode: CharArray, salt: ByteArray): SecretKey { | |
// Initialize PBE with password | |
val factory: SecretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") | |
val spec: KeySpec = PBEKeySpec(passcode, salt, 65536, 256) | |
val tmp: SecretKey = factory.generateSecret(spec) | |
return SecretKeySpec(tmp.encoded, "AES") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment