如何在Kotlin Android中获取Xamarin SecureStorage存储的数据?
在Android Kotlin中读取Xamarin SecureStorage存储的数据
核心原理
Xamarin.Essentials的SecureStorage在Android端的存储逻辑如下:
- 密钥:使用Android KeyStore生成AES密钥,默认别名为
xamarin_essentials_secure_storage(API 23+);API 23以下使用RSA密钥(当前设备占比极低) - 数据:明文经密钥加密后,以Base64格式存储在名为
Xamarin.Essentials.Preferences的SharedPreferences中,键名与调用SecureStorage.SetAsync时传入的一致
实现步骤(Kotlin代码)
1. 读取加密数据
从对应SharedPreferences中取出Base64编码的加密字符串:
val sharedPrefs = context.getSharedPreferences("Xamarin.Essentials.Preferences", Context.MODE_PRIVATE) val encryptedValue = sharedPrefs.getString("你的存储键名", null) ?: return null
2. 获取KeyStore中的解密密钥
从Android KeyStore中读取Xamarin生成的默认密钥:
private fun getXamarinSecureStorageKey(): SecretKey? { return try { val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) } val entry = keyStore.getEntry("xamarin_essentials_secure_storage", null) as? KeyStore.SecretKeyEntry entry?.secretKey } catch (e: Exception) { e.printStackTrace() null } }
3. 解密数据
Xamarin采用AES/GCM加密,加密后的数据格式为[IV(16字节)][密文][GCM Tag(16字节)],解密时需拆分并处理:
private fun decryptData(encryptedBase64: String, key: SecretKey): String? { return try { val decodedBytes = Base64.decode(encryptedBase64, Base64.DEFAULT) // 拆分IV、密文、Tag val iv = decodedBytes.copyOfRange(0, 16) val ciphertext = decodedBytes.copyOfRange(16, decodedBytes.size - 16) val tag = decodedBytes.copyOfRange(decodedBytes.size - 16, decodedBytes.size) val cipher = Cipher.getInstance("AES/GCM/NoPadding") val spec = GCMParameterSpec(128, iv) cipher.init(Cipher.DECRYPT_MODE, key, spec) // 合并密文与Tag,执行解密 val combined = ByteArray(ciphertext.size + tag.size) System.arraycopy(ciphertext, 0, combined, 0, ciphertext.size) System.arraycopy(tag, 0, combined, ciphertext.size, tag.size) val decryptedBytes = cipher.doFinal(combined) String(decryptedBytes, Charsets.UTF_8) } catch (e: Exception) { e.printStackTrace() null } }
4. 整合调用
将上述逻辑封装为可直接调用的方法:
fun getXamarinSecureStorageValue(context: Context, key: String): String? { // 读取加密数据 val sharedPrefs = context.getSharedPreferences("Xamarin.Essentials.Preferences", Context.MODE_PRIVATE) val encryptedBase64 = sharedPrefs.getString(key, null) ?: return null // 获取密钥 val secretKey = getXamarinSecureStorageKey() ?: return null // 解密并返回明文 return decryptData(encryptedBase64, secretKey) }
关键注意事项
- 包名一致性:你的Kotlin应用必须与原Xamarin应用的包名完全相同,否则无法访问沙箱内的SharedPreferences和KeyStore密钥
- API兼容:如果需要兼容API 23以下设备,需调整为RSA解密逻辑(密钥为RSA私钥,加密算法为
RSA/ECB/PKCS1Padding) - 无额外权限:访问自身应用的SharedPreferences和KeyStore无需申请特殊权限
内容的提问来源于stack exchange,提问作者Fried Rice
相关产品推荐
相关产品推荐

