Skip to content

Commit cff04f4

Browse files
committed
Make sure the key store alias is globally unique
If a user has installed multiple apps with this SDK, Android will throw an exception when the second app tries to use the same key pair alias. This will crash our SDK and the App. This commit makes sure the key is unique by including the property id in the string.
1 parent 1955bdd commit cff04f4

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

lib/src/main/java/de/contentpass/lib/ContentPass.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class ContentPass internal constructor(
112112
fun build(): ContentPass {
113113
configuration = grabConfiguration()
114114
val authorizer = Authorizer(configuration!!, context!!)
115-
val store = TokenStore(context!!, KeyStore(context!!))
115+
val store = TokenStore(context!!, KeyStore(context!!, configuration!!.propertyId))
116116
return ContentPass(authorizer, store, configuration!!)
117117
}
118118

lib/src/main/java/de/contentpass/lib/KeyStore.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import javax.crypto.spec.SecretKeySpec
1818
import javax.security.auth.x500.X500Principal
1919
import java.security.KeyStore as VendorKeyStore
2020

21-
internal class KeyStore(private val context: Context) {
21+
internal class KeyStore(private val context: Context, private val propertyId: String) {
2222
private val keystoreName = "AndroidKeyStore"
23-
private val keyPairAlias = "de.contentpass.KeyPair"
23+
private val keyPairAlias = "de.contentpass.KeyPair.$propertyId"
2424
private val privateKey: PrivateKey
2525
private val publicKey: PublicKey
2626
private val keystore = VendorKeyStore.getInstance(keystoreName)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package de.contentpass.lib
2+
3+
import android.content.Context
4+
import io.mockk.mockk
5+
import org.junit.Assert.assertEquals
6+
import org.junit.Test
7+
import java.lang.reflect.Field
8+
9+
class KeyStoreTests {
10+
11+
@Test
12+
fun `key pair alias contains property id`() {
13+
val propertyId = "test-property-123"
14+
val context: Context = mockk(relaxed = true)
15+
16+
// Use reflection to access the private keyPairAlias field
17+
val keyStore = KeyStore(context, propertyId)
18+
val keyPairAliasField: Field = KeyStore::class.java.getDeclaredField("keyPairAlias")
19+
keyPairAliasField.isAccessible = true
20+
val keyPairAlias: String = keyPairAliasField.get(keyStore) as String
21+
22+
// Verify the alias contains the property ID
23+
assertEquals("de.contentpass.KeyPair.$propertyId", keyPairAlias)
24+
assertEquals(true, keyPairAlias.contains(propertyId))
25+
}
26+
27+
@Test
28+
fun `key pair alias uses different property ids correctly`() {
29+
val propertyId1 = "property-one"
30+
val propertyId2 = "property-two"
31+
val context: Context = mockk(relaxed = true)
32+
33+
// Create two KeyStore instances with different property IDs
34+
val keyStore1 = KeyStore(context, propertyId1)
35+
val keyStore2 = KeyStore(context, propertyId2)
36+
37+
val keyPairAliasField: Field = KeyStore::class.java.getDeclaredField("keyPairAlias")
38+
keyPairAliasField.isAccessible = true
39+
40+
val alias1: String = keyPairAliasField.get(keyStore1) as String
41+
val alias2: String = keyPairAliasField.get(keyStore2) as String
42+
43+
// Verify each alias contains its respective property ID
44+
assertEquals("de.contentpass.KeyPair.$propertyId1", alias1)
45+
assertEquals("de.contentpass.KeyPair.$propertyId2", alias2)
46+
47+
// Verify they are different
48+
assertEquals(false, alias1 == alias2)
49+
}
50+
}
51+

0 commit comments

Comments
 (0)