Kotlin 使用非对称用户授权保护的密钥库密钥加密大字符串时出现问题
我正在尝试为JWToken的加密和解密实现生物认证。 用户在服务器上进行身份验证后,将接收令牌并对其进行加密。加密 在没有生物特征用户授权的情况下,应允许在设备上使用令牌。 只有解密操作才需要生物识别设备授权。这就是为什么我 为此使用非对称密钥。然而,我收到的令牌大约是1000字节,因此 无法使用非对称密钥加密。这就是我创建对称密钥进行解密的原因 和加密操作,并使用受授权保护的非对称密钥包装和打开此密钥。 但是,尝试用非对称公钥包装对称密钥会引发InvalidKeyException with 消息:javax.crypto.BadPaddingException。尝试用非对称私钥包装对称密钥 这次还抛出InvalidKeyException,并显示简短消息:未能打开密钥。当我设置UserAuthenticationRequired时 若要使非对称私钥为false,则可以很好地进行包装。我做错了什么Kotlin 使用非对称用户授权保护的密钥库密钥加密大字符串时出现问题,kotlin,encryption,android-keystore,android-biometric,Kotlin,Encryption,Android Keystore,Android Biometric,我正在尝试为JWToken的加密和解密实现生物认证。 用户在服务器上进行身份验证后,将接收令牌并对其进行加密。加密 在没有生物特征用户授权的情况下,应允许在设备上使用令牌。 只有解密操作才需要生物识别设备授权。这就是为什么我 为此使用非对称密钥。然而,我收到的令牌大约是1000字节,因此 无法使用非对称密钥加密。这就是我创建对称密钥进行解密的原因 和加密操作,并使用受授权保护的非对称密钥包装和打开此密钥。 但是,尝试用非对称公钥包装对称密钥会引发InvalidKeyException with
class EncryptionService(
private val wrappedKeyStoreSource: WrappedKeyStore2
) {
companion object {
const val MASTER_KEY = "master_key"
const val ALGORITHM_AES = "AES"
const val ENCRYPTION_KEY = "encryption_key"
const val TRANSFORMATION_ASYMMETRIC = "RSA/ECB/PKCS1Padding"
const val TRANSFORMATION_SYMMETRIC = "AES/CBC/PKCS7Padding"
}
private val keyStore: KeyStore = createAndroidKeyStore()
init {
createDefaultSymmetricKey()
}
fun encrypt(data: String): String =
encryptWithSymmetricKey(data)
private fun createDefaultSymmetricKey() {
val symmetricKey = generateSymmetricKey()
val masterKey = createAsymmetricKey(MASTER_KEY)
val cipher: Cipher = Cipher.getInstance(TRANSFORMATION_ASYMMETRIC)
cipher.init(Cipher.WRAP_MODE, masterKey.public)
val encryptedSymmetricKey = cipher.wrap(symmetricKey)
wrappedKeyStoreSource.saveKey(ENCRYPTION_KEY, Base64.encodeToString(encryptedSymmetricKey, Base64.DEFAULT) )
}
//encrypt without user authorization
private fun encryptWithSymmetricKey(data: String): String {
val masterKey = getAsymmetricKeyPair(MASTER_KEY)
val encryptionKey = wrappedKeyStoreSource.getKey(ENCRYPTION_KEY)
val unwrapCipher: Cipher = Cipher.getInstance(TRANSFORMATION_ASYMMETRIC)
unwrapCipher.init(Cipher.UNWRAP_MODE, masterKey?.public)
val encryptedKeyData = Base64.decode(encryptionKey, Base64.DEFAULT)
//this line throws InvalidKeyException
//unwrap with public key throws InvalidKeyException with message: javax.crypto.BadPaddingException.
//unwrap with private key throws InvalidKeyException if setUserAuthenticationRequired on this
// key is set to true with message: Failed to unwrap key (maybe due to UserNotAuthenticatedException?)
val symmetricKey = unwrapCipher.unwrap(encryptedKeyData, ALGORITHM_AES, Cipher.PUBLIC_KEY) as SecretKey
val encryptCipher: Cipher = Cipher.getInstance(TRANSFORMATION_SYMMETRIC)
encryptCipher.init(Cipher.ENCRYPT_MODE, symmetricKey)
val encryptedString = encryptCipher.doFinal(data.toByteArray())
return Base64.encodeToString(encryptedString, Base64.DEFAULT)
}
private fun createAsymmetricKey(alias: String): KeyPair {
val generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore")
val builder = KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_ECB)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.setUserAuthenticationRequired(true)
generator.initialize(builder.build())
return generator.generateKeyPair()
}
private fun generateSymmetricKey(): SecretKey {
val keyGenerator = KeyGenerator.getInstance("AES")
return keyGenerator.generateKey()
}
private fun getAsymmetricKeyPair(alias: String): KeyPair? {
val privateKey = keyStore.getKey(alias, null) as PrivateKey?
val publicKey = keyStore.getCertificate(alias)?.publicKey
return if (privateKey != null && publicKey != null) {
KeyPair(publicKey, privateKey)
} else {
null
}
}
private fun createAndroidKeyStore(): KeyStore {
val keyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(null)
return keyStore
}
}
当我切换到使用私钥展开时,如下所示
unwrapCipher.init(Cipher.UNWRAP_MODE, masterKey?.private)
val encryptedKeyData = Base64.decode(encryptionKey, Base64.DEFAULT)
val symmetricKey = unwrapCipher.unwrap(encryptedKeyData, ALGORITHM_AES, Cipher.SECRET_KEY) as SecretKey
我得到了以下线索
stackTrace: java.security.InvalidKeyException: Failed to unwrap key
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineUnwrap(AndroidKeyStoreCipherSpiBase.java:682)
at javax.crypto.Cipher.unwrap(Cipher.java:2440)
at com.libencryption.data.EncryptionService.encryptWithSymmetricKey(EncryptionService.kt:58)
at com.libencryption.data.EncryptionService.encrypt(EncryptionService.kt:37)
我假设这是由于我将UserAuthenticationRequired设置为true导致的,因为当我将其设置为false时,所有加密都很好。但是,正如您从stackstrace中看到的,没有记录异常。有没有其他原因导致setUserAuthenticationRequired为true时失败?在公钥/私钥加密中,加密是用公钥完成的,解密是用私钥执行的。不要试图解释异常所说的话,而是发布整个异常堆栈跟踪,并告诉我们代码中的哪一行触发了异常。更好的是,还包括实际涉及的关键点。我们的目标是有一个完整的例子来说明这个问题。我的错误。那么,还有其他选择吗?除了:-用户使用对称密钥授权每个加密-手动分离数据并使用公共非对称密钥加密其部分key@PresidentJamesK.Polk. 我添加了stacktrace,并在引发异常的地方添加了注释。我不太清楚你说的包括实际钥匙是什么意思。我的意思是,对不起。在函数“EncryptWithSymmetyKey”中,您试图使用以下代码行打开(使用RSA加密的)对称密钥:“unwrapipher.init(Cipher.unwrap_模式,masterKey?.public)”。您正在尝试使用公钥展开=解密-尝试更改为私钥。
stackTrace: java.security.InvalidKeyException: Failed to unwrap key
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineUnwrap(AndroidKeyStoreCipherSpiBase.java:682)
at javax.crypto.Cipher.unwrap(Cipher.java:2440)
at com.libencryption.data.EncryptionService.encryptWithSymmetricKey(EncryptionService.kt:58)
at com.libencryption.data.EncryptionService.encrypt(EncryptionService.kt:37)