gpt4 book ai didi

android - 2021 年在 Android 中加密字符串的最佳和最安全的方法是什么?

转载 作者:行者123 更新时间:2023-12-05 00:02:25 27 4
gpt4 key购买 nike

我惊讶地发现 Jatpack Security 提供了 only support for File and SharedPreferences encryption .但我需要能够加密和解密String s 因为我想使用 AccountManager并存储刷新和访问 token ,以及官方文档中建议的这种数据 should be send encrypted to the AccountManager :
https://developer.android.com/training/id-auth/custom_auth#Security
网上搜索有很多关于如何加密的教程String s 在 Android 上,但它们中的大多数似乎已经很老了,我害怕选择错误的可能会导致 Play Store Console 上出现这种警告:
enter image description here
那么,加密 String 的正确和安全方法是什么? s 在 2021 年的 Android 应用程序中? Jetpack Security 还能在一定程度上使用(也许是生成 key ?)以及为什么它不支持开箱即用的字符串加密,而只支持 File s 和 SharedPreferences ?

最佳答案

深入了解 EncryptedSharedPreferences 的实现后和 EncryptedFile ,我设法创建了一个 CryptoHelper该类使用与 Jetpack Security 的 2 个类相同的方法,提供加密、解密、签名和验证的方法 ByteArray年代:

import android.content.Context
import androidx.security.crypto.MasterKeys
import com.google.crypto.tink.Aead
import com.google.crypto.tink.DeterministicAead
import com.google.crypto.tink.KeyTemplate
import com.google.crypto.tink.KeyTemplates
import com.google.crypto.tink.PublicKeySign
import com.google.crypto.tink.PublicKeyVerify
import com.google.crypto.tink.aead.AeadConfig
import com.google.crypto.tink.daead.DeterministicAeadConfig
import com.google.crypto.tink.integration.android.AndroidKeysetManager
import com.google.crypto.tink.signature.SignatureConfig
import java.io.IOException
import java.security.GeneralSecurityException

/**
* Class used to encrypt, decrypt, sign ad verify data.
*
* <pre>
* // Encrypt
* val cypherText = cryptoHelper.encrypt(text.toByteArray())
* // Decrypt
* val plainText = cryptoHelper.decrypt(cypherText)
* // Sign
* val signature = cryptoHelper.sign(text.toByteArray())
* // Verify
* val verified = cryptoHelper.verify(signature, text.toByteArray())
* </pre>
*/
@Suppress("unused")
class CryptoHelper(
private val aead: Aead,
private val deterministicAead: DeterministicAead,
private val signer: PublicKeySign,
private val verifier: PublicKeyVerify,
) {

/**
* Builder class to configure CryptoHelper
*/
class Builder(
// Required parameters
private val context: Context,
) {
// Optional parameters
private var masterKeyAlias: String = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
private var keysetPrefName = KEYSET_PREF_NAME
private var keysetAlias = KEYSET_ALIAS
private var aeadKeyTemplate: KeyTemplate
private var deterministicAeadKeyTemplate: KeyTemplate
private var signKeyTemplate: KeyTemplate

init {
AeadConfig.register()
DeterministicAeadConfig.register()
SignatureConfig.register()
aeadKeyTemplate = KeyTemplates.get("AES256_GCM")
deterministicAeadKeyTemplate = KeyTemplates.get("AES256_SIV")
signKeyTemplate = KeyTemplates.get("ECDSA_P256")
}

/**
* @param masterKey The SharedPreferences file to store the keyset.
* @return This Builder
*/
fun setMasterKey(masterKey: String): Builder {
this.masterKeyAlias = masterKey
return this
}

/**
* @param keysetPrefName The SharedPreferences file to store the keyset.
* @return This Builder
*/
fun setKeysetPrefName(keysetPrefName: String): Builder {
this.keysetPrefName = keysetPrefName
return this
}

/**
* @param keysetAlias The alias in the SharedPreferences file to store the keyset.
* @return This Builder
*/
fun setKeysetAlias(keysetAlias: String): Builder {
this.keysetAlias = keysetAlias
return this
}

/**
* @param keyTemplate If the keyset for Aead encryption is not found or valid, generates a new one using keyTemplate.
* @return This Builder
*/
fun setAeadKeyTemplate(keyTemplate: KeyTemplate): Builder {
this.aeadKeyTemplate = keyTemplate
return this
}

/**
* @param keyTemplate If the keyset for deterministic Aead encryption is not found or valid, generates a new one using keyTemplate.
* @return This Builder
*/
fun setDeterministicAeadKeyTemplate(keyTemplate: KeyTemplate): Builder {
this.deterministicAeadKeyTemplate = keyTemplate
return this
}

/**
* @param keyTemplate If the keyset for signing/verifying is not found or valid, generates a new one using keyTemplate.
* @return This Builder
*/
fun setSignKeyTemplate(keyTemplate: KeyTemplate): Builder {
this.signKeyTemplate = keyTemplate
return this
}

/**
* @return An CryptoHelper with the specified parameters.
*/
@Throws(GeneralSecurityException::class, IOException::class)
fun build(): CryptoHelper {
val aeadKeysetHandle = AndroidKeysetManager.Builder()
.withKeyTemplate(aeadKeyTemplate)
.withSharedPref(context, keysetAlias + "_aead__", keysetPrefName)
.withMasterKeyUri(KEYSTORE_PATH_URI + masterKeyAlias)
.build().keysetHandle
val deterministicAeadKeysetHandle = AndroidKeysetManager.Builder()
.withKeyTemplate(deterministicAeadKeyTemplate)
.withSharedPref(context, keysetAlias + "_daead__", keysetPrefName)
.withMasterKeyUri(KEYSTORE_PATH_URI + masterKeyAlias)
.build().keysetHandle
val signKeysetHandle = AndroidKeysetManager.Builder()
.withKeyTemplate(signKeyTemplate)
.withSharedPref(context, keysetAlias + "_sign__", keysetPrefName)
.withMasterKeyUri(KEYSTORE_PATH_URI + masterKeyAlias)
.build().keysetHandle
val aead = aeadKeysetHandle.getPrimitive(Aead::class.java)
val deterministicAead = deterministicAeadKeysetHandle.getPrimitive(DeterministicAead::class.java)
val signer = signKeysetHandle.getPrimitive(PublicKeySign::class.java)
val verifier = signKeysetHandle.publicKeysetHandle.getPrimitive(PublicKeyVerify::class.java)
return CryptoHelper(aead, deterministicAead, signer, verifier)
}
}

fun encrypt(plainText: ByteArray, associatedData: ByteArray = ByteArray(0)): ByteArray =
aead.encrypt(plainText, associatedData)

fun decrypt(ciphertext: ByteArray, associatedData: ByteArray = ByteArray(0)): ByteArray =
aead.decrypt(ciphertext, associatedData)

fun encryptDeterministically(plainText: ByteArray, associatedData: ByteArray = ByteArray(0)): ByteArray =
deterministicAead.encryptDeterministically(plainText, associatedData)

fun decryptDeterministically(ciphertext: ByteArray, associatedData: ByteArray = ByteArray(0)): ByteArray =
deterministicAead.decryptDeterministically(ciphertext, associatedData)

fun sign(data: ByteArray): ByteArray =
signer.sign(data)

fun verify(signature: ByteArray, data: ByteArray): Boolean =
try {
verifier.verify(signature, data)
true
} catch (e: GeneralSecurityException) {
false
}

companion object {
private const val KEYSTORE_PATH_URI = "android-keystore://"
private const val KEYSET_PREF_NAME = "__crypto_helper_pref__"
private const val KEYSET_ALIAS = "__crypto_helper_keyset"
}
}

不要忘记添加 com.google.crypto.tink:tink-android作为实现依赖项,因为 Jetpack Security 不会将其公开为 api。

关于android - 2021 年在 Android 中加密字符串的最佳和最安全的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69953633/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com