PHP:解密从 Kotlin 加密收到的字符串

问题描述 投票:0回答:1

我使用以下代码在 Kotlin 中加密了一个字符串

private fun encrypt(context: Context, strToEncrypt: String, encryptKey : String): ByteArray {
        
        val plainText = strToEncrypt.toByteArray(Charsets.UTF_8)
        val key = generateKey(encryptKey)
        val cipher = Cipher.getInstance("AES_256/CBC/PKCS5PADDING")
        cipher.init(Cipher.ENCRYPT_MODE, key)
        val cipherText = cipher.doFinal(plainText)
        return cipherText
    }

    private fun generateKey(password: String): SecretKeySpec {

        val digest: MessageDigest = MessageDigest.getInstance("SHA-256")
        val bytes = password.toByteArray()
        digest.update(bytes, 0, bytes.size)
        val key = digest.digest()
        val secretKeySpec = SecretKeySpec(key, "AES")
        return secretKeySpec
    }

我这样使用它:

encrypt(requireContext(), "test_string", "password")

现在我需要解密 PHP 中生成的字符串(通过 GET 接收字符串)。我有这样的东西:

function decryptString($encryptedString, $cipher, $key, $initVector) {

    // decrypt and return string
    return openssl_decrypt($encryptedString, $cipher, $key, 0, $initVector);
}

if (isset($_GET["plain_text"])) {
    
    // define cipher algorithm
    $cipher = "aes-256-cbc";

    // generate initialization vector
    $iv_size = openssl_cipher_iv_length($cipher);
    $iv = openssl_random_pseudo_bytes($iv_size);

    echo decryptString($_GET["plain_text"], $cipher, "password", $iv);
}

但是结果是空的。我想这是因为在 PHP 中我可以使用一个字符串作为我定义的描述的键(

$key
过程中的
openssl_decrypt()
参数),而在 Kotlin 中(该死的 Android 总是无缘无故地过于复杂),你是被迫使用
SecretKeySpec
参数作为键,因此我无法传递硬编码字符串作为键。

我不是加密专家,所以请原谅我这个愚蠢的问题。

php kotlin encryption openssl aes
1个回答
0
投票

Kotlin 代码会自动生成一个随机 IV,您必须将其与密文一起获取并传递。将两者连接起来是很常见的,例如iv|密文。您可以使用 Base64 从字节数组生成字符串:

private fun encrypt(strToEncrypt: String, encryptKey : String): String {
    val plainText = strToEncrypt.toByteArray(Charsets.UTF_8)
    val key = generateKey(encryptKey)
    val cipher = Cipher.getInstance("AES_256/CBC/PKCS5PADDING")
    cipher.init(Cipher.ENCRYPT_MODE, key)
    val cipherText = cipher.iv + cipher.doFinal(plainText) // get IV and concatenate with ciphertext
    return Base64.getEncoder().encodeToString(cipherText)  // Base64 encode data
}

在 PHP 方面,必须从密文中剥离 IV。此外,密钥必须像 Kotlin 代码中一样使用 SHA256 导出(顺便说一句,最好使用 PBKDF2 或更现代的 KDF):

$ivCt = base64_decode('p5ONPQVga2KWX5nM1mHI04uXRYCqFXUTYgsiIurQdfF+qidI5YOOjhn2s9g/DYuq'); // sample data from Kotlin code
$iv = substr($ivCt, 0, 16); // strip IV off
$ct = substr($ivCt, 16);
$pwd = 'your password';
$key = hash('sha256', $pwd, true); // derive key with SHA256
$dt = openssl_decrypt($ct, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); // disable default Base64 with OPENSSL_RAW_DATA 
print($dt . PHP_EOL); // Take me to your leader
© www.soinside.com 2019 - 2024. All rights reserved.