11package de.contentpass.lib
22
33import android.content.Context
4- import android.security.KeyPairGeneratorSpec
5- import java.math.BigInteger
4+ import android.security.keystore.KeyGenParameterSpec
5+ import android.security.keystore.KeyProperties
66import java.security.KeyPair
77import java.security.KeyPairGenerator
88import java.security.PrivateKey
99import java.security.PublicKey
1010import java.security.spec.MGF1ParameterSpec
11- import java.util.Calendar
1211import javax.crypto.Cipher
1312import javax.crypto.KeyGenerator
1413import javax.crypto.SecretKey
1514import javax.crypto.spec.OAEPParameterSpec
1615import javax.crypto.spec.PSource
1716import javax.crypto.spec.SecretKeySpec
18- import javax.security.auth.x500.X500Principal
1917import java.security.KeyStore as VendorKeyStore
2018
2119internal class KeyStore (private val context : Context , private val propertyId : String ) {
@@ -58,38 +56,50 @@ internal class KeyStore(private val context: Context, private val propertyId: St
5856 }
5957
6058 private fun createKeyPair (): KeyPair {
61- val spec = buildKeyPairGeneratorSpec()
62- val generator = KeyPairGenerator .getInstance(" RSA" , " AndroidKeyStore" )
63- generator.initialize(spec)
59+ val spec = buildKeyGenParameterSpec()
60+ val generator = KeyPairGenerator .getInstance(
61+ KeyProperties .KEY_ALGORITHM_RSA ,
62+ " AndroidKeyStore"
63+ )
64+ generator.initialize(spec as java.security.spec.AlgorithmParameterSpec )
6465
6566 return generator.generateKeyPair()
6667 }
6768
68- private fun buildKeyPairGeneratorSpec (): KeyPairGeneratorSpec {
69- val start = Calendar .getInstance()
70- val end = Calendar .getInstance()
71- end.add(Calendar .YEAR , 1 )
72-
73- return KeyPairGeneratorSpec .Builder (context)
74- .setAlias(keyPairAlias)
75- .setSubject(X500Principal (" CN=Sample Name, O=Android Authority" ))
76- .setSerialNumber(BigInteger .ONE )
77- .setStartDate(start.time)
78- .setEndDate(end.time)
69+ private fun buildKeyGenParameterSpec (): KeyGenParameterSpec {
70+ return KeyGenParameterSpec .Builder (
71+ keyPairAlias,
72+ KeyProperties .PURPOSE_ENCRYPT or KeyProperties .PURPOSE_DECRYPT
73+ )
74+ .setKeySize(2048 )
75+ .setDigests(KeyProperties .DIGEST_SHA256 )
76+ .setEncryptionPaddings(KeyProperties .ENCRYPTION_PADDING_RSA_OAEP )
7977 .build()
8078 }
8179
8280 private fun retrieveKey (): SecretKey ? {
83- return sharedPreferences.getString(sharedPreferencesKey, null )?.let {
84- val encrypted = it.decoded()
85- return decryptKey(encrypted)
81+ return sharedPreferences.getString(sharedPreferencesKey, null )?.let { encryptedString ->
82+ try {
83+ val encrypted = encryptedString.decoded()
84+ decryptKey(encrypted)
85+ } catch (e: Exception ) {
86+ // If decryption fails, the stored key might be corrupted
87+ // Return null to trigger key regeneration
88+ null
89+ }
8690 }
8791 }
8892
8993 private fun decryptKey (encryptedKey : ByteArray ): SecretKey {
90- cipher.init (Cipher .DECRYPT_MODE , privateKey, paddingSpec)
91- val decrypted = cipher.doFinal(encryptedKey)
92- return SecretKeySpec (decrypted, " AES" )
94+ try {
95+ cipher.init (Cipher .DECRYPT_MODE , privateKey, paddingSpec)
96+ val decrypted = cipher.doFinal(encryptedKey)
97+ return SecretKeySpec (decrypted, " AES" )
98+ } catch (e: javax.crypto.IllegalBlockSizeException ) {
99+ // If decryption fails due to block size issues, try to regenerate the key
100+ // by deleting the corrupted entry and creating a new one
101+ throw IllegalStateException (" Failed to decrypt stored key. Key may be corrupted." , e)
102+ }
93103 }
94104
95105 private fun createKey (): SecretKey {
@@ -110,8 +120,12 @@ internal class KeyStore(private val context: Context, private val propertyId: St
110120 }
111121
112122 private fun encryptKey (key : SecretKey ): ByteArray {
113- cipher.init (Cipher .ENCRYPT_MODE , publicKey, paddingSpec)
114- return cipher.doFinal(key.encoded)
123+ try {
124+ cipher.init (Cipher .ENCRYPT_MODE , publicKey, paddingSpec)
125+ return cipher.doFinal(key.encoded)
126+ } catch (e: javax.crypto.IllegalBlockSizeException ) {
127+ throw IllegalStateException (" Failed to encrypt key. Key size may be incompatible." , e)
128+ }
115129 }
116130}
117131
0 commit comments