PHP 和 Android 密钥库加密/解密
PHP and Android Keystore encryption / decryption
几个小时以来,我一直在尝试获取此信息,但我找不到问题所在。我正在使用我制作的 php RESTful API 来使用非对称加密来加密数据。
首先,我通过将用户的 public 密钥导出到 android:
来将其保存在服务器中
fun exportPublicKey() : String {
val publicKey = getPublicKey()
return android.util.Base64.encodeToString(
publicKey!!.encoded,
android.util.Base64.NO_WRAP
)
}
这允许我在 PHP 服务器中执行此操作:
$public_key_core = $_POST["public_key"];
$public_key = "-----BEGIN PUBLIC KEY-----\n" . $public_key_core . "\n-----END PUBLIC KEY-----";
我不确定这是正确的方法,但 openssl 似乎“可以”使用该密钥?
然后我使用这两个密钥在本地测试了我的密钥库,使用此代码它工作得很好:
加密:
fun encryptAsymmetricData(data: String, usePrivateKey : Boolean = true): ByteArray {
val cipher : Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
val encryptedBytes: ByteArray
if (usePrivateKey){
cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey())
encryptedBytes = cipher.doFinal(data.toByteArray(Charsets.UTF_8))
} else {
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey())
encryptedBytes= cipher.doFinal(data.toByteArray(Charsets.UTF_8))
}
return encryptedBytes
}
解密:
fun decryptAsymmetricData(data: ByteArray): String{
val cipher : Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey())
return cipher.doFinal(data).toString(Charsets.UTF_8)
}
使用它是有效的,因为我对 encryptData 结果执行了“.toByteArray(Charsets.UTF_8)”。
现在问题来了,我使用 base64 编码并执行以下操作以在 PHP:
中加密
openssl_public_encrypt($token->token, $encrypted_token, $user->public_key);
openssl_public_encrypt($user->id, $encrypted_id, $user->public_key);
[...]
'encrypted_user_id' => base64_encode($encrypted_id),
'encrypted_token' => base64_encode($encrypted_token)
但是当我尝试在 Android 中解密时,我遇到了由以下代码引起的异常“javax.crypto.IllegalBlockSizeException”:
val tokenBA = String(getDecoder().decode(this.encryptedToken), Charsets.UTF_8).toByteArray(Charsets.UTF_8)
val userIDBA = String(getDecoder().decode(this.encryptedUserId), Charsets.UTF_8).toByteArray(Charsets.UTF_8)
val token = App.encryptionController.decryptAsymmetricData(tokenBA)
val userID = App.encryptionController.decryptAsymmetricData(userIDBA)
(逻辑是,我在 PHP 中使用 base64 发回我的数据,所以我在 Android 中将其转换为 UTF8,然后获取关联的 ByteArray 来解密它?)
我知道加密在“本地”中有效,但在同时使用 PHP 和 KeyStore 时无效,所以我猜问题要么来自 PHP 加密,要么来自我尝试在 android 中解密它的方式,但我似乎找不到什么问题,你们能帮我吗?
提前致谢!
好的,在搜索并确定问题不是存储在 PHP 服务器中的 public 密钥之后,我找到了答案。这是由于在应用程序中将“base64”字符串转换为实际的ByteArray 的方式造成的。这有效:
val token = App.encryptionController.decryptAsymmetricData(getDecoder().decode(encryptedToken))
val userID = App.encryptionController.decryptAsymmetricData(getDecoder().decode(encryptedUserId))
这之所以有效,是因为我在服务器中执行了“base64_encode”,出于某些(不好的)原因,我认为需要返回到 UTF8 才能在应用程序中获取 ByteArray。
几个小时以来,我一直在尝试获取此信息,但我找不到问题所在。我正在使用我制作的 php RESTful API 来使用非对称加密来加密数据。
首先,我通过将用户的 public 密钥导出到 android:
来将其保存在服务器中fun exportPublicKey() : String {
val publicKey = getPublicKey()
return android.util.Base64.encodeToString(
publicKey!!.encoded,
android.util.Base64.NO_WRAP
)
}
这允许我在 PHP 服务器中执行此操作:
$public_key_core = $_POST["public_key"];
$public_key = "-----BEGIN PUBLIC KEY-----\n" . $public_key_core . "\n-----END PUBLIC KEY-----";
我不确定这是正确的方法,但 openssl 似乎“可以”使用该密钥?
然后我使用这两个密钥在本地测试了我的密钥库,使用此代码它工作得很好:
加密:
fun encryptAsymmetricData(data: String, usePrivateKey : Boolean = true): ByteArray {
val cipher : Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
val encryptedBytes: ByteArray
if (usePrivateKey){
cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey())
encryptedBytes = cipher.doFinal(data.toByteArray(Charsets.UTF_8))
} else {
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey())
encryptedBytes= cipher.doFinal(data.toByteArray(Charsets.UTF_8))
}
return encryptedBytes
}
解密:
fun decryptAsymmetricData(data: ByteArray): String{
val cipher : Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey())
return cipher.doFinal(data).toString(Charsets.UTF_8)
}
使用它是有效的,因为我对 encryptData 结果执行了“.toByteArray(Charsets.UTF_8)”。 现在问题来了,我使用 base64 编码并执行以下操作以在 PHP:
中加密openssl_public_encrypt($token->token, $encrypted_token, $user->public_key);
openssl_public_encrypt($user->id, $encrypted_id, $user->public_key);
[...]
'encrypted_user_id' => base64_encode($encrypted_id),
'encrypted_token' => base64_encode($encrypted_token)
但是当我尝试在 Android 中解密时,我遇到了由以下代码引起的异常“javax.crypto.IllegalBlockSizeException”:
val tokenBA = String(getDecoder().decode(this.encryptedToken), Charsets.UTF_8).toByteArray(Charsets.UTF_8)
val userIDBA = String(getDecoder().decode(this.encryptedUserId), Charsets.UTF_8).toByteArray(Charsets.UTF_8)
val token = App.encryptionController.decryptAsymmetricData(tokenBA)
val userID = App.encryptionController.decryptAsymmetricData(userIDBA)
(逻辑是,我在 PHP 中使用 base64 发回我的数据,所以我在 Android 中将其转换为 UTF8,然后获取关联的 ByteArray 来解密它?)
我知道加密在“本地”中有效,但在同时使用 PHP 和 KeyStore 时无效,所以我猜问题要么来自 PHP 加密,要么来自我尝试在 android 中解密它的方式,但我似乎找不到什么问题,你们能帮我吗?
提前致谢!
好的,在搜索并确定问题不是存储在 PHP 服务器中的 public 密钥之后,我找到了答案。这是由于在应用程序中将“base64”字符串转换为实际的ByteArray 的方式造成的。这有效:
val token = App.encryptionController.decryptAsymmetricData(getDecoder().decode(encryptedToken))
val userID = App.encryptionController.decryptAsymmetricData(getDecoder().decode(encryptedUserId))
这之所以有效,是因为我在服务器中执行了“base64_encode”,出于某些(不好的)原因,我认为需要返回到 UTF8 才能在应用程序中获取 ByteArray。