【发布时间】:2020-09-06 10:23:33
【问题描述】:
我正在开发一个安卓应用。
我想将一些敏感数据(jwt 令牌)加密/解密到 SharedPreference 中。
所以我写了下面的代码。
fun initKeyStore() {
val alias = "${packageName}.rsakeypairs"
val keyStore = KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
}
if (keyStore.containsAlias(alias)) {
} else {
SLog.d(LogTag.SECURE, "[cipher] No keypair for $alias, creating a new one")
with(KeyPairGenerator.getInstance(KEY_ALGORITHM_RSA, "AndroidKeyStore"), {
val spec = KeyGenParameterSpec.Builder(alias,
PURPOSE_ENCRYPT or PURPOSE_DECRYPT)
.setAlgorithmParameterSpec(RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4))
.setBlockModes(BLOCK_MODE_CBC)
.setEncryptionPaddings(ENCRYPTION_PADDING_RSA_PKCS1)
.setDigests(DIGEST_SHA512, DIGEST_SHA384, DIGEST_SHA256)
.setUserAuthenticationRequired(false)
.build()
initialize(spec)
generateKeyPair()
})
}
keyEntry = keyStore.getEntry(alias, null)
}
fun String.encrypt(): String? {
cipher.init(Cipher.ENCRYPT_MODE, (keyEntry as KeyStore.PrivateKeyEntry).certificate.publicKey)
val bytes = this.toByteArray(Charsets.UTF_8)
val encryptedBytes = cipher.doFinal(bytes)
val base64EncryptedBytes = Base64.encode(encryptedBytes, Base64.DEFAULT)
return String(base64EncryptedBytes)
}
fun String.decrypt(): String {
cipher.init(Cipher.DECRYPT_MODE, (keyEntry as KeyStore.PrivateKeyEntry).privateKey)
val base64EncryptedBytes = this.toByteArray(Charsets.UTF_8)
val encryptedBytes = Base64.decode(base64EncryptedBytes, Base64.DEFAULT)
val decryptedBytes = cipher.doFinal(encryptedBytes)
return String(decryptedBytes)
}
但是当应用尝试解密加密数据时,发生了异常。
javax.crypto.IllegalBlockSizeException
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:513)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)
...
Caused by: android.security.KeyStoreException: Invalid input length
at android.security.KeyStore.getKeyStoreException(KeyStore.java:1539)
at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.update(KeyStoreCryptoOperationChunkedStreamer.java:132)
我使用的 JWT 令牌的长度很长。 (超过 800 个)
如果我尝试加密/解密短文本,它可以正常工作...
如何加密/解密长文本?
【问题讨论】:
-
.setBlockModes(BLOCK_MODE_CBC)对 RSA 没有意义。我会假设它只是被忽略了,但谁知道呢。此外,加密和解密方向需要自己的 Cipher 实例。
标签: android encryption rsa