我正在尝试为 JWToken 的加密和解密实现生物特征认证。用户在服务器上进行身份验证后,将接收并加密令牌。令牌的加密应该允许在设备上没有生物特征用户授权的情况下进行。只有解密操作需要生物识别设备授权。这就是我为此使用非对称密钥的原因。然而,我收到的令牌大约是 1000 字节,因此不能用非对称密钥加密。这就是为什么我为解密和加密操作创建一个对称密钥,并使用授权保护的非对称密钥包装和解包这个密钥。但是,尝试使用非对称公钥包装对称密钥会引发 InvalidKeyException,并显示消息:javax.crypto.BadPaddingException。尝试用非对称私钥包装对称密钥这次也会抛出 InvalidKeyException 并显示简短消息:无法解开密钥。当我 setUserAuthenticationRequired 为 false 时,非对称私钥可以很好地用于包装。我在这里做错了什么?
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
}
}
stackTrace: java.security.InvalidKeyException: javax.crypto.BadPaddingException:
error:0400006b:RSA routines:OPENSSL_internal:BLOCK_TYPE_IS_NOT_01
at com.android.org.conscrypt.OpenSSLCipherRSA.engineUnwrap(OpenSSLCipherRSA.java:373)
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)
当我切换到使用私钥解包时,如下所示
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)
我认为这是因为我 setUserAuthenticationRequired 为 true ,因为当我将其设置为 false 时,一切都加密得很好。但是,正如您从 stackstrace 中看到的那样,没有记录异常。是否有任何其他原因导致 setUserAuthenticationRequired 为 true 时会失败?