Decrypt aes encrypted file in java sha1 openssl

前端 未结 1 1655
没有蜡笔的小新
没有蜡笔的小新 2021-01-29 16:48

Im trying to implement file decryption by referring this code:

Encryption part i have done this way: https//stackoverflow.com/questions/64423926/encrypt-file-in-java-and-

相关标签:
1条回答
  • 2021-01-29 16:59

    The below code is doing a complete file encryption and decryption and is compatible to the OpenSSL commands

    encrypt: openssl enc -aes-256-cbc -pass pass:testpass -d -p -in plaintext.txt -out plaintext.txt.crypt -md md5
    decrypt: openssl aes-256-cbc -d -in plaintext.txt.crypt -out plaintext1.txt -k testpass -md md5
    

    I left out some variables as they are not used in decryption method and on the other hand substituded the byte[] concatination with a pure Java version.

    The simple output is:

    encrypt done plaintext.txt
    ciphertext: plaintext.txt
    Decrypt is completed
    

    Security warning: the key derivation is DEPRECATED and should not used any longer. The code does not have any exception handling and is for educational purpose only.

    code:

    import javax.crypto.Cipher;
    import javax.crypto.CipherOutputStream;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.security.*;
    import java.util.Arrays;
    
    public class MainSo {
        public static void main(String[] args) {
            System.out.println("https://stackoverflow.com/questions/64443373/decrypt-aes-encrypted-file-in-java-sha1-openssl?noredirect=1#comment113960588_64443373");
            String plaintextFilename = "plaintext.txt";
            String ciphertextFilename = "plaintext.txt.crypt";
            String decryptedtextFilename = "plaintextDecrypted.txt";
            String password = "testpass";
    
            // openssl equivalent:
            // decrypt: openssl aes-256-cbc -d -in plaintext.txt.crypt -out plaintext1.txt -k testpass -md md5
            // encrypt: openssl enc -aes-256-cbc -pass pass:testpass -d -p -in sample.crypt -out sample.txt -md md5
    
            String ciphertext = encryptfile(plaintextFilename, password);
            System.out.println("ciphertext: " + ciphertext);
            decryptNew(ciphertextFilename, password, decryptedtextFilename);
        }
    
        public static String encryptfile(String path, String password) {
            try {
                FileInputStream fis = new FileInputStream(path);
                FileOutputStream fos = new FileOutputStream(path.concat(".crypt"));
                final byte[] pass = password.getBytes(StandardCharsets.UTF_8);
                final byte[] salt = (new SecureRandom()).generateSeed(8);
                fos.write("Salted__".getBytes(StandardCharsets.UTF_8));
                fos.write(salt);
                final byte[] passAndSalt = concatenateByteArrays(pass, salt);
                byte[] hash = new byte[0];
                byte[] keyAndIv = new byte[0];
                for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
                    final byte[] hashData = concatenateByteArrays(hash, passAndSalt);
                    final MessageDigest md = MessageDigest.getInstance("MD5");
                    hash = md.digest(hashData);
                    keyAndIv = concatenateByteArrays(keyAndIv, hash);
                }
                final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
                final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);
                final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");
                final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
                CipherOutputStream cos = new CipherOutputStream(fos, cipher);
                int b;
                byte[] d = new byte[8];
                while ((b = fis.read(d)) != -1) {
                    cos.write(d, 0, b);
                }
                cos.flush();
                cos.close();
                fis.close();
                System.out.println("encrypt done " + path);
            } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            }
            return path;
        }
    
        static void decryptNew(String path,String password, String outPath) {
            byte[] SALTED_MAGIC = "Salted__".getBytes(StandardCharsets.UTF_8);
            try{
                FileInputStream fis = new FileInputStream(path);
                FileOutputStream fos = new FileOutputStream(outPath);
                final byte[] pass = password.getBytes(StandardCharsets.US_ASCII);
                final byte[] inBytes = Files.readAllBytes(Paths.get(path));
                final byte[] shouldBeMagic = Arrays.copyOfRange(inBytes, 0, SALTED_MAGIC.length);
                if (!Arrays.equals(shouldBeMagic, SALTED_MAGIC)) {
                    throw new IllegalArgumentException("Initial bytes from input do not match OpenSSL SALTED_MAGIC salt value.");
                }
                final byte[] salt = Arrays.copyOfRange(inBytes, SALTED_MAGIC.length, SALTED_MAGIC.length + 8);
                final byte[] passAndSalt = concatenateByteArrays(pass, salt);
                byte[] hash = new byte[0];
                byte[] keyAndIv = new byte[0];
                for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
                    final byte[] hashData = concatenateByteArrays(hash, passAndSalt);
                    MessageDigest md = null;
                    md = MessageDigest.getInstance("MD5");
                    hash = md.digest(hashData);
                    keyAndIv = concatenateByteArrays(keyAndIv, hash);
                }
                final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
                final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");
                final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);
                final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
                final byte[] clear = cipher.doFinal(inBytes, 16, inBytes.length - 16);
                String contentDecoded = new String(clear, StandardCharsets.UTF_8);
                fos.write(contentDecoded.getBytes());
                fos.close();
                System.out.println("Decrypt is completed");
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    
        public static byte[] concatenateByteArrays(byte[] a, byte[] b) {
            return ByteBuffer
                    .allocate(a.length + b.length)
                    .put(a).put(b)
                    .array();
        }
    }
    
    0 讨论(0)
提交回复
热议问题