How to decrypt file in Java encrypted with openssl command using AES?

前端 未结 4 1723
萌比男神i
萌比男神i 2020-11-22 13:31

I need to decrypt in JAVA a file encrypted in UNIX with the following command:

openssl aes-256-cbc -a -salt -in password.txt -out password.txt.enc
mypass
myp         


        
4条回答
  •  情深已故
    2020-11-22 13:59

    In Kotlin:

    package io.matthewnelson.java_crypto
    
    import java.util.*
    import javax.crypto.Cipher
    import javax.crypto.SecretKeyFactory
    import javax.crypto.spec.IvParameterSpec
    import javax.crypto.spec.PBEKeySpec
    import javax.crypto.spec.SecretKeySpec
    
    class OpenSSL {
    
        /**
         * Will decrypt a string value encrypted by OpenSSL v 1.1.1+ using the following cmds from terminal:
         *
         *   echo "Hello World!" | openssl aes-256-cbc -e -a -p -salt -pbkdf2 -iter 15739 -k qk4aX-EfMUa-g4HdF-fjfkU-bbLNx-15739
         *
         * Terminal output:
         *   salt=CC73B7D29FE59CE1
         *   key=31706F84185EA4B5E8E040F2C813F79722F22996B48B82FF98174F887A9B9993
         *   iv =1420310D41FD7F48E5D8722B9AC1C8DD
         *   U2FsdGVkX1/Mc7fSn+Wc4XLwDsmLdR8O7K3bFPpCglA=
         * */
        fun decrypt_AES256CBC_PBKDF2_HMAC_SHA256(
            password: String,
            hashIterations: Int,
            encryptedString: String
        ): String {
            val encryptedBytes = Base64.getDecoder().decode(encryptedString)
    
            // Salt is bytes 8 - 15
            val salt = encryptedBytes.copyOfRange(8, 16)
    //        println("Salt: ${salt.joinToString("") { "%02X".format(it) }}")
    
            // Derive 48 byte key
            val keySpec = PBEKeySpec(password.toCharArray(), salt, hashIterations, 48 * 8)
            val keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
            val secretKey = keyFactory.generateSecret(keySpec)
    
            // Decryption Key is bytes 0 - 31 of the derived key
            val key = secretKey.encoded.copyOfRange(0, 32)
    //        println("Key: ${key.joinToString("") { "%02X".format(it) }}")
    
            // Input Vector is bytes 32 - 47 of the derived key
            val iv = secretKey.encoded.copyOfRange(32, 48)
    //        println("IV: ${iv.joinToString("") { "%02X".format(it) }}")
    
            // Cipher Text is bytes 16 - end of the encrypted bytes
            val cipherText = encryptedBytes.copyOfRange(16, encryptedBytes.lastIndex + 1)
    
            // Decrypt the Cipher Text and manually remove padding after
            val cipher = Cipher.getInstance("AES/CBC/NoPadding")
            cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
            val decrypted = cipher.doFinal(cipherText)
    //        println("Decrypted: ${decrypted.joinToString("") { "%02X".format(it) }}")
    
            // Last byte of the decrypted text is the number of padding bytes needed to remove
            val plaintext = decrypted.copyOfRange(0, decrypted.lastIndex + 1 - decrypted.last().toInt())
    
            return plaintext.toString(Charsets.UTF_8)
        }
    }
    

提交回复
热议问题