【发布时间】:2018-12-14 15:51:22
【问题描述】:
我正在尝试使用由java.security.KeyPairGenerator 的实例生成的密钥对来加密任意字符串。不幸的是,使用生成的 KeyPair 对字符串进行加密和解密后,结果不正确。
这就是我的做法:
val ks: KeyStore = KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
}
fun encryptUsingKey(publicKey: PublicKey, bytes: ByteArray): ByteArray {
val inCipher = Cipher.getInstance("RSA/NONE/NoPadding")
inCipher.init(Cipher.ENCRYPT_MODE, publicKey)
return inCipher.doFinal(bytes)
}
fun decryptUsingKey(privateKey: PrivateKey, bytes: ByteArray): ByteArray {
val inCipher = Cipher.getInstance("RSA/NONE/NoPadding")
inCipher.init(Cipher.DECRYPT_MODE, privateKey)
return inCipher.doFinal(bytes)
}
fun getKey(): KeyStore.Entry {
val containsAlias = ks.containsAlias(alias)
if (!containsAlias) {
val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA,
"AndroidKeyStore"
)
val parameterSpec: KeyGenParameterSpec =
KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT
)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setRandomizedEncryptionRequired(false)
.build()
kpg.initialize(parameterSpec)
val kp = kpg.generateKeyPair()
}
return ks.getEntry(alias, null)
}
我的加密/解密测试如下:
fun testEncryptionDecryption() {
val entry = getKey()
if (entry is KeyStore.PrivateKeyEntry) {
val privateKey = entry.privateKey
val certificate = entry.certificate
val publicKey = certificate.publicKey
val testKey = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
val encrypted = service.encryptUsingKey(publicKey, Base64.decodeFromString(testKey))
val decrypted = service.decryptUsingKey(privateKey, encrypted)
assertEquals(testKey, Base64.encodeToString(decrypted))
}
}
不幸的是,结果如下所示:
org.junit.ComparisonFailure: expected:<[0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF]> but was:<[AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANNdt-Oeu_PQAQgxBdNdt-Oeu_PQAQgxBdNdt-Oeu_PQAQgxBdNdt-Oeu_PQAQgxBQ]>
有人可以告诉我这里发生了什么吗?所有这些 A 是从哪里来的?我是不是用错了钥匙?
【问题讨论】:
-
将 RSA 与
NoPadding一起使用既不安全也不正确。 RSA解密需要知道明文的长度。 RSA 随机填充处理了这一点以及安全需求。 OAEP 填充是目前最适合 RSA 的,所以使用它, -
@JamesKPolk 我试图采纳您的建议,但现在我收到了
java.security.InvalidKeyException: Keystore operation failed异常... -
您是否更改了
setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)以反映您使用的填充? -
是的,我将其设置为
KeyProperties.ENCRYPTION_PADDING_RSA_OAEP并使用Cipher.getInstance("RSA/NONE/OAEPPadding")获取密码 -
@AKroell 你为什么使用 RSA? AES 会更快(耗电量更少),而且看起来您实际上并不需要 RSA 的非对称属性。
标签: android encryption kotlin android-keystore