Closed carlbenson closed 7 years ago
@carlbenson How reproducible is it? And just a trivial question: you can sure that getKeyPair()
always return the same key?
I cannot reproduce it, it seems to be device dependent? The keys are taken from an Android Key Store entry and created if not present so it should stay the same. Cannot think of a reason for a Android Key Store entry to change for an already installed app.
Hi @carlbenson Are you generating an AES from an asymmetric key? How are you initialising the KeyStore?
is it possible to see the code where you obtain the key. the Android KeyStore have some subtle differences sometimes given the version of Android.
@nhachicha here is the code that initialises and fetches keys from the key store
fun getKeyPair(context: Context, entryKey: String): KeyPair {
val keyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(null)
val entry = keyStore.getEntry(entryKey, null)
if (entry is KeyStore.PrivateKeyEntry) {
return KeyPair(entry.certificate.publicKey, entry.privateKey)
} else {
val keyGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore")
keyGenerator.initialize(getAlgorithmParameterSpec(context, entryKey))
return keyGenerator.generateKeyPair()
}
}
private fun getAlgorithmParameterSpec(context: Context, entryKey: String): AlgorithmParameterSpec {
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
val notBefore = Calendar.getInstance()
val notAfter = Calendar.getInstance()
notAfter.add(1, Calendar.YEAR)
KeyPairGeneratorSpec.Builder(context)
.setAlias(entryKey)
.setKeyType(KeyProperties.KEY_ALGORITHM_RSA)
.setKeySize(2048)
.setSubject(X500Principal(String.format("CN=Dreams, OU=%s, C=SE", context.packageName)))
.setSerialNumber(BigInteger.ONE)
.setStartDate(notBefore.time)
.setEndDate(notAfter.time)
.build()
} else {
KeyGenParameterSpec.Builder(entryKey, KeyProperties.PURPOSE_DECRYPT or
KeyProperties.PURPOSE_ENCRYPT or
KeyProperties.PURPOSE_SIGN or
KeyProperties.PURPOSE_VERIFY)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.setBlockModes(KeyProperties.BLOCK_MODE_ECB)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setKeySize(2048)
.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
.build()
}
}
AFAICT you're using the key only for encryption/decryption
setSignaturePaddings
is used for signing/verification.
try setting instead
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
Can you try with this configuration and see if it's reproducible on the mentioned devices?
I am setting encryption paddings, 4 lines above setting signature paddings. I cannot change configurations and invalid thousands of user's sessions and ask them to login in again. Like I said, it only happens randomly in our user base, and I cannot reproduce it. Also, it only seems to happen on API < 23 devices.
Also, for realm, I'm only using the 512 first bits of the generated key (which is 2048 bites and used in backend communication where it works perfectly).
@carlbenson android.keystore is unreliable. if the data is not in your app/data/data folder, u are at the mercy of android fragmentation. https://code.google.com/p/android/issues/detail?id=61989
@diegomontoya yes this is what I have been fearing too, but it is very unclear from the Android docs if this is the intended behaviour or a bug. I think the solution will be for us to invalid the user session, remove their key from the keystore, create a new one and require a new login (will create a new realm file).
We get these crash reports from some of our customers of our app
Our configuration is very simple
Version of Realm and tooling
Realm version(s): 2.2.1
Realm sync feature enabled: no
Android Studio version: 2.2.2
Which Android version and device: Android versions 4.4, 5.0 and 5.1, running on HTC One (m7), Sony Xperia X (F5121), Sony, Xperia Z (C6603),LG G3, Samsung Galaxy Grand Max