文件加密和解密在java中不起作用

ryoqjall  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(451)

这个问题在这里已经有了答案

使用cipherinputstream和cipheroutputstream加密和解密文件(1个答案)
25天前关门了。
我想加密一个叫做 largefile.mp4 最有效的方法,然后再次解密,但它并没有像预期的那样工作。
实际上没有任何错误,并且文件被生成。但是新生成的文件比主文件小。
在这里 largefile.mp4 是100mb但是 newEncryptedFile.txt 是107kb newDecryptedFile.mp4 是210字节
有什么问题?

package fileenc;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

public class FileEncrypterDecrypter {

    SecretKey key;
    Cipher cipher;

    public FileEncrypterDecrypter() {

        try {

            KeyGenerator keygen = KeyGenerator.getInstance("AES");

            key = keygen.generateKey();

            cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {

            System.out.println(e);
        }

    }

    public boolean fileEncrypt(String plainFile) {

        try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(plainFile))){

            cipher.init(Cipher.ENCRYPT_MODE, key);
            FileOutputStream fs = new FileOutputStream("newEncryptedFile.txt");
            CipherOutputStream out = new CipherOutputStream(fs, cipher);

            byte[] byteSize = new byte[1024];

            int numberOfBytedRead;

            while ( (numberOfBytedRead = fis.read(byteSize)) != -1 ) {
                out.write(numberOfBytedRead);
            }

            fis.close();
            out.flush();
            out.close();

            System.out.println("Encryption done...");

            return true;

        } catch (IOException | InvalidKeyException e) {

        }

        return false;
    }

    public boolean fileDecrypt(String encryptedFile) {

        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("newDecryptedFile.mp4"))){

            cipher.init(Cipher.DECRYPT_MODE, key);
            FileInputStream fis = new FileInputStream(encryptedFile);
            CipherInputStream in = new CipherInputStream(fis, cipher);

            byte[] byteSize = new byte[1024];

            int numberOfBytedRead;

            while ( (numberOfBytedRead = in.read(byteSize)) != -1) {
                bos.write(numberOfBytedRead);
            }

            System.out.println("Decryption done...");

            bos.flush();
            bos.close();
            in.close();

            return true;

        } catch (IOException | InvalidKeyException e) {

        }

        return false;
    }

    public static void main(String[] args) throws FileNotFoundException, IOException {

        FileEncrypterDecrypter fed = new FileEncrypterDecrypter();

        fed.fileEncrypt("largefile.mp4"); // about 100 mb
        fed.fileDecrypt("newEncryptedFile.txt");

    }
}
7hiiyaii

7hiiyaii1#

很抱歉,我没有检查您的代码,因为您使用的是不安全模式,不应再在新项目中使用。
下面是在cbc模式下使用aes进行文件加密和解密的示例代码。该程序生成一个用于加密和解密的随机密钥(使用base64编码中的out-of-the-key以获得更好的存储),生成一个随机初始化向量(iv),该向量写在加密文件的开头。
对于解密,前16个字节作为未加密数据读取,所有其他数据通过解密流。
加密是在cipheroutput-/inputstream的帮助下以8192字节的块进行的。
安全警告:该代码没有任何异常处理,仅用于教育目的。请注意,为了提高安全性,您可以更改为经过身份验证的加密(例如,使用hmac或gcm模式进行保护)。
输出:

AES CBC 256 file encryption with CipherOutputStream
encryption key in base64 encoding: vTsd0E8MX3arfLRFjxZ58FSjkKxKYe32+rT5zCnJPVY=
result encryption: true
result decryption: true

代码:

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

public class AesCbcEncryptionWithRandomKeyCipherOutputStreamSoExample {
    public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException,
            InvalidKeyException, InvalidAlgorithmParameterException {
        System.out.println("AES CBC 256 file encryption with CipherOutputStream");
        String uncryptedFilename = "plaintext.txt";
        String encryptedFilename = "encrypted.enc";
        String decryptedFilename = "decrypted.txt";

        // generate random aes 256 key
        byte[] encryptionKey = new byte[32];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(encryptionKey);
        System.out.println("encryption key in base64 encoding: " + base64Encoding(encryptionKey));
        boolean result;
        // encryption
        result = encryptCbcFileBufferedCipherOutputStream(uncryptedFilename, encryptedFilename, encryptionKey);
        System.out.println("result encryption: " + result);
        // decryption
        result = decryptCbcFileBufferedCipherInputStream(encryptedFilename, decryptedFilename, encryptionKey);
        System.out.println("result decryption: " + result);
    }

    public static boolean encryptCbcFileBufferedCipherOutputStream(String inputFilename, String outputFilename, byte[] key)
            throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
        // generate random iv
        SecureRandom secureRandom = new SecureRandom();
        byte[] iv = new byte[16];
        secureRandom.nextBytes(iv);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        try (FileInputStream in = new FileInputStream(inputFilename);
             FileOutputStream out = new FileOutputStream(outputFilename);
             CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
            out.write(iv);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] buffer = new byte[8096];
            int nread;
            while ((nread = in.read(buffer)) > 0) {
                encryptedOutputStream.write(buffer, 0, nread);
            }
            encryptedOutputStream.flush();
        }
        if (new File(outputFilename).exists()) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean decryptCbcFileBufferedCipherInputStream(String inputFilename, String outputFilename, byte[] key) throws
            IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
        byte[] iv = new byte[16];
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        try (FileInputStream in = new FileInputStream(inputFilename);
             CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
             FileOutputStream out = new FileOutputStream(outputFilename))
        {
            byte[] buffer = new byte[8192];
            in.read(iv);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            int nread;
            while ((nread = cipherInputStream.read(buffer)) > 0) {
                out.write(buffer, 0, nread);
            }
            out.flush();
        }
        if (new File(outputFilename).exists()) {
            return true;
        } else {
            return false;
        }
    }

    private static String base64Encoding(byte[] input) {
        return Base64.getEncoder().encodeToString(input);
    }
}

相关问题