这个文件解密有什么问题吗? (Kotlin/AndroidStudio)

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

我正在编写一个应用程序,让您通过 ssh 连接到远程计算机。 我想保护 ssh 密钥,所以我的想法是对其进行加密,然后在应用程序内部对其进行解密。

这是我正在使用的功能:

    fun decryptFileWithPBKDF2(
        encryptedFile: File,
        decryptedFile: File,
        password: String,
        iterations: Int = 10000,
        keyLength: Int = 256
    ) {
        val saltSize = 8 // OpenSSL salt is 8 bytes
        val ivSize = 16 // AES block size is 16 bytes for CBC mode
        val headerSize = 8 // Salted__ is the first 8 bytes

        FileInputStream(encryptedFile).use { fis ->
            val fileBytes = fis.readBytes()

            // Check if the file is at least large enough to contain the header, salt, and IV
            if (fileBytes.size < headerSize + saltSize + ivSize) {
                throw IllegalArgumentException("Invalid encrypted file format.")
            }

            // Extract the salt (bytes 8 to 15) and IV (bytes 16 to 31)
            val salt = fileBytes.sliceArray(headerSize until headerSize + saltSize)
            val iv = fileBytes.sliceArray(headerSize + saltSize until headerSize + saltSize + ivSize)

            // Ciphertext starts after "Salted__", salt, and IV (total 32 bytes)
            val cipherText = fileBytes.sliceArray(headerSize + saltSize + ivSize until fileBytes.size)

            // Derive the key using PBKDF2 with the same parameters as OpenSSL
            val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
            val spec: KeySpec = PBEKeySpec(password.toCharArray(), salt, iterations, keyLength)
            val tmp = factory.generateSecret(spec)
            val secretKey = SecretKeySpec(tmp.encoded, "AES")

            // Initialize AES cipher for decryption (AES/CBC/PKCS5Padding)
            val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
            cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(iv))

            // Decrypt the file
            val decryptedBytes = cipher.doFinal(cipherText)

            // Write the decrypted content to the output file
            FileOutputStream(decryptedFile).use { fos ->
                fos.write(decryptedBytes)
            }
        }
    }

这是我的 test.txt 中的全文: “这是一条严肃的信息!我不知道为什么解密会毁掉这段精彩的文字:(” 由于某种原因,解密后看起来像这样: “这是一条严肃的信息!我不知道为什么解密会毁掉这个精彩的文本:(”

我加密了这样的文件:

openssl enc -aes-256-cbc -pbkdf2 -salt -in test.txt -out test.enc -k "password" -p

你能帮我解决这个问题吗?

我尝试使用所有三大主要人工智能助手,但没有成功。

android kotlin encryption
1个回答
0
投票

OpenSSL 语句生成的数据结构如下(

|
表示串联):

<ASCII encoding of Salted__>|<8 bytes salt>|<ciphertext>

因此,使用 PBKDF2 从密码和盐中派生出密钥和 IV。

然而,您在 Kotlin 代码中错误地假设 IV 也包含在数据中,但事实并非如此。相反,IV 必须与密钥一起导出,例如如下:

...
// Extract the salt (bytes 8 to 15) 
val salt = fileBytes.sliceArray(headerSize until headerSize + saltSize)

// Ciphertext starts after "Salted__", salt (total 16 bytes)
val cipherText = fileBytes.sliceArray(headerSize + saltSize until fileBytes.size)

// Derive the key and IV using PBKDF2 with the same parameters as OpenSSL
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
val spec: KeySpec = PBEKeySpec(password.toCharArray(), salt, iterations, keyLength + ivSize * 8)
val tmp = factory.generateSecret(spec)

val key = tmp.encoded.sliceArray(0 until keyLength/8)
val iv = tmp.encoded.sliceArray(keyLength/8 until keyLength/8 + ivSize)
val secretKey = SecretKeySpec(key, "AES")
...

通过此更改,解密有效。

© www.soinside.com 2019 - 2024. All rights reserved.