@account-kit/react-native-signer 4.8.0 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.accountkit.reactnativesigner.core
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
+
import android.content.SharedPreferences
|
|
4
5
|
import androidx.security.crypto.EncryptedSharedPreferences
|
|
5
6
|
import androidx.security.crypto.MasterKey
|
|
6
7
|
import com.accountkit.reactnativesigner.core.errors.NoInjectedBundleException
|
|
@@ -19,6 +20,8 @@ import java.nio.ByteBuffer
|
|
|
19
20
|
import java.security.KeyFactory
|
|
20
21
|
import java.security.Security
|
|
21
22
|
import java.security.Signature
|
|
23
|
+
import java.security.KeyStore
|
|
24
|
+
import java.security.KeyStoreException
|
|
22
25
|
|
|
23
26
|
@Serializable
|
|
24
27
|
data class ApiStamp(val publicKey: String, val scheme: String, val signature: String)
|
|
@@ -27,6 +30,8 @@ data class Stamp(val stampHeaderName: String, val stampHeaderValue: String)
|
|
|
27
30
|
|
|
28
31
|
private const val BUNDLE_PRIVATE_KEY = "BUNDLE_PRIVATE_KEY"
|
|
29
32
|
private const val BUNDLE_PUBLIC_KEY = "BUNDLE_PUBLIC_KEY"
|
|
33
|
+
private const val MASTER_KEY_ALIAS = "tek_master_key"
|
|
34
|
+
private const val ENCRYPTED_SHARED_PREFERENCES_FILENAME = "tek_stamper_shared_prefs"
|
|
30
35
|
|
|
31
36
|
class TEKStamper(context: Context) {
|
|
32
37
|
// This is how the docs for EncryptedSharedPreferences recommend creating this setup
|
|
@@ -36,12 +41,6 @@ class TEKStamper(context: Context) {
|
|
|
36
41
|
//
|
|
37
42
|
// we should explore the best practices on how to do this once we reach a phase of further
|
|
38
43
|
// cleanup
|
|
39
|
-
private val masterKey =
|
|
40
|
-
MasterKey.Builder(context.applicationContext)
|
|
41
|
-
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
|
42
|
-
// requires that the phone be unlocked
|
|
43
|
-
.setUserAuthenticationRequired(false)
|
|
44
|
-
.build()
|
|
45
44
|
|
|
46
45
|
/**
|
|
47
46
|
* We are using EncryptedSharedPreferences to store 2 pieces of data
|
|
@@ -64,29 +63,35 @@ class TEKStamper(context: Context) {
|
|
|
64
63
|
*
|
|
65
64
|
* The open question is if the storage of the decrypted private key is secure enough though
|
|
66
65
|
*/
|
|
67
|
-
|
|
68
|
-
EncryptedSharedPreferences.create(
|
|
69
|
-
context,
|
|
70
|
-
"tek_stamper_shared_prefs",
|
|
71
|
-
masterKey,
|
|
72
|
-
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
73
|
-
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
74
|
-
)
|
|
66
|
+
|
|
75
67
|
|
|
76
|
-
private val tekManager = HpkeTEKManager(sharedPreferences)
|
|
77
68
|
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
|
|
70
|
+
|
|
80
71
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
private lateinit var tekManager: HpkeTEKManager
|
|
73
|
+
private lateinit var sharedPreferences: SharedPreferences
|
|
74
|
+
|
|
75
|
+
init {
|
|
76
|
+
try {
|
|
77
|
+
TinkConfig.register()
|
|
78
|
+
|
|
79
|
+
sharedPreferences = getSharedPreferences(context)
|
|
80
|
+
tekManager = HpkeTEKManager(sharedPreferences)
|
|
81
|
+
|
|
82
|
+
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME).javaClass !=
|
|
83
|
+
BouncyCastleProvider::class.java
|
|
84
|
+
) {
|
|
85
|
+
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
|
|
89
|
+
Security.addProvider(BouncyCastleProvider())
|
|
90
|
+
}
|
|
91
|
+
} catch (e: Exception){
|
|
92
|
+
throw RuntimeException("Error creating master key", e)
|
|
89
93
|
}
|
|
94
|
+
|
|
90
95
|
}
|
|
91
96
|
|
|
92
97
|
fun init(): String {
|
|
@@ -196,4 +201,58 @@ class TEKStamper(context: Context) {
|
|
|
196
201
|
)
|
|
197
202
|
return Pair(compressedPublicKey, privateKey)
|
|
198
203
|
}
|
|
204
|
+
|
|
205
|
+
private fun createSharedPreferences(masterKey: MasterKey, context: Context): SharedPreferences {
|
|
206
|
+
return EncryptedSharedPreferences.create(
|
|
207
|
+
context,
|
|
208
|
+
ENCRYPTED_SHARED_PREFERENCES_FILENAME,
|
|
209
|
+
masterKey,
|
|
210
|
+
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
211
|
+
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private fun createMasterKey(context: Context): MasterKey {
|
|
216
|
+
return MasterKey.Builder(context.applicationContext, MASTER_KEY_ALIAS)
|
|
217
|
+
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
|
218
|
+
.setUserAuthenticationRequired(false)
|
|
219
|
+
.build()
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
private fun getSharedPreferences(context: Context): SharedPreferences {
|
|
224
|
+
try {
|
|
225
|
+
// Attempt to create or load the EncryptedSharedPreferences file
|
|
226
|
+
val masterKey = createMasterKey(context)
|
|
227
|
+
|
|
228
|
+
return createSharedPreferences(masterKey, context)
|
|
229
|
+
} catch(e: Exception) {
|
|
230
|
+
// Log the Exception
|
|
231
|
+
e.printStackTrace()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// An error occured creating or retrieving the Shared Preferences file.
|
|
235
|
+
// Delete the existing master key and EncryptedSharedPreferences
|
|
236
|
+
|
|
237
|
+
// first delete the MasterKey
|
|
238
|
+
try {
|
|
239
|
+
val keyStore = KeyStore.getInstance("AndroidKeyStore")
|
|
240
|
+
keyStore.load(null)
|
|
241
|
+
keyStore.deleteEntry(MASTER_KEY_ALIAS)
|
|
242
|
+
} catch (keyStoreDeletionException: Exception) {
|
|
243
|
+
throw RuntimeException("An error occured deleting the Master Key", keyStoreDeletionException)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// attempt to recreate a new EncryptedSharedPreferences file
|
|
247
|
+
try {
|
|
248
|
+
// Create a new MasterKey
|
|
249
|
+
val newMasterKey = createMasterKey(context)
|
|
250
|
+
context.getSharedPreferences(ENCRYPTED_SHARED_PREFERENCES_FILENAME, Context.MODE_PRIVATE).edit().clear().apply()
|
|
251
|
+
context.deleteSharedPreferences(ENCRYPTED_SHARED_PREFERENCES_FILENAME)
|
|
252
|
+
|
|
253
|
+
return createSharedPreferences(newMasterKey, context)
|
|
254
|
+
} catch(retryException: Exception) {
|
|
255
|
+
throw RuntimeException("Couldn't create the required shared preferences file. Ensure you are properly authenticated on this device.", retryException)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
199
258
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@account-kit/react-native-signer",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.0",
|
|
4
4
|
"author": "Alchemy",
|
|
5
5
|
"description": "React Native compatible Account Kit signer",
|
|
6
6
|
"source": "./src/index.tsx",
|
|
@@ -147,9 +147,9 @@
|
|
|
147
147
|
"version": "0.42.2"
|
|
148
148
|
},
|
|
149
149
|
"dependencies": {
|
|
150
|
-
"@aa-sdk/core": "^4.
|
|
151
|
-
"@account-kit/signer": "^4.
|
|
150
|
+
"@aa-sdk/core": "^4.9.0",
|
|
151
|
+
"@account-kit/signer": "^4.9.0",
|
|
152
152
|
"viem": "^2.21.40"
|
|
153
153
|
},
|
|
154
|
-
"gitHead": "
|
|
154
|
+
"gitHead": "9cd4dc759879defa6ac90f1ae7f8a378d9d1666f"
|
|
155
155
|
}
|