Я пытался получить это в течение нескольких часов, и я не могу найти, что не так. Я использую php RESTful API, который я сделал для шифрования данных с использованием асимметричного шифрования.
Во-первых, я сохраняю открытый ключ моего пользователя на сервере, экспортируя его в 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)
}
Использование этого работает, потому что я делаю «.toByteArray (Charsets.UTF_8)» для результата encryptData. Теперь вот проблема, я использую кодировку 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)
(Логика заключается в том, что я использую base64 для отправки моих данных в PHP, поэтому я конвертирую их в UTF8 в Android, а затем получаю связанный ByteArray для их расшифровки?)
Я знаю, что шифрование работает «локально», но не при использовании PHP и KeyStore, поэтому я предполагаю, что проблема возникает либо из-за шифрования PHP, либо из-за того, как я пытаюсь расшифровать его в Android, но я могу кажется, не нахожу, что не так, не могли бы вы, ребята, помочь мне, пожалуйста?
Заранее спасибо!
Хорошо, после поиска и проверки того, что проблема не в открытом ключе, хранящемся на сервере PHP, я нашел ответ. Это было вызвано способом преобразования строки «base64» в фактический массив байтов в приложении. Это сработало:
val token = App.encryptionController.decryptAsymmetricData(getDecoder().decode(encryptedToken))
val userID = App.encryptionController.decryptAsymmetricData(getDecoder().decode(encryptedUserId))
Это работает только потому, что я делаю «base64_encode» на сервере, по какой-то (плохой) причине я думал, что нужно вернуться к UTF8, чтобы получить ByteArray в приложении.