如何加密分割文件的每个部分

时间:2018-07-14 11:20:55

标签: java file encryption file-io

我有一个可以将给定文件拆分并合并为多个文件的类,但是我想知道如何在拆分时加密每个文件,然后在再次合并时解密。

这是文件拆分和合并的类。

public void splitFile(File f) throws Exception {
    int partCounter = 1;

    int sizeOfFiles = (int) (f.length() / 3);
    byte[] buffer = new byte[sizeOfFiles];

    String fileName = f.getName();
    String destFileName = fileName.substring(0, fileName.lastIndexOf('.')) + "." + FilenameUtils.getExtension(fileName);

    try (FileInputStream fis = new FileInputStream(f);
            BufferedInputStream bis = new BufferedInputStream(fis)) {

        int bytesAmount = 0;

        while ((bytesAmount = bis.read(buffer)) > 0) {

            String filePartName = String.format("%s.%03d", destFileName, partCounter++);
            File newFile = new File("D:\\FileTest\\", filePartName);
            try (FileOutputStream out = new FileOutputStream(newFile)) {
                //I think this is how you encrypt each split part before it gets written to a file?
                out.write(FileEncrypt.encrypt(buffer, encKey), 0, bytesAmount);
            }
        }
        bos.close();
    }
}

public List<File> listOfFilesToMerge(File oneOfFiles) throws IOException, Exception {
    String tmpName = oneOfFiles.getName();
    String destFileName = tmpName.substring(0, tmpName.lastIndexOf('.'));
    File[] files = oneOfFiles.getParentFile().listFiles((File dir, String name) -> name.matches(destFileName + "[.]\\d+"));
    Arrays.sort(files);
    for (File f : files) {
        //And this is how to decrypt the files before it gets merged?
        FileEncrypt.decrypt(Files.readAllBytes(f.toPath()), encKey);
    }
    return Arrays.asList(files);
}

public void mergeFiles(List<File> files, File into) throws Exception {
    try (FileOutputStream fos = new FileOutputStream(into);
            BufferedOutputStream mergingStream = new BufferedOutputStream(fos)) {
        for (File f : files) {
            Files.copy(f.toPath(), mergingStream);
        }
    }
}

这是加密类。

public static byte[] encrypt(byte[] bytes, String key) throws Exception {
    byte[] iv = new byte[ivSize];
    SecureRandom random = new SecureRandom();
    random.nextBytes(iv);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.update(key.getBytes("UTF-8"));
    byte[] keyBytes = new byte[keySize];
    System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] encrypted = cipher.doFinal(bytes);

    byte[] encryptedIVAndFile = new byte[ivSize + encrypted.length];
    System.arraycopy(iv, 0, encryptedIVAndFile, 0, ivSize);
    System.arraycopy(encrypted, 0, encryptedIVAndFile, ivSize, encrypted.length);

    return encryptedIVAndFile;
}

public static byte[] decrypt(byte[] encryptedIvFileBytes, String key) throws Exception {
    byte[] iv = new byte[ivSize];
    System.arraycopy(encryptedIvFileBytes, 0, iv, 0, iv.length);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

    int encryptedSize = encryptedIvFileBytes.length - ivSize;
    byte[] encryptedBytes = new byte[encryptedSize];
    System.arraycopy(encryptedIvFileBytes, ivSize, encryptedBytes, 0, encryptedSize);

    byte[] keyBytes = new byte[keySize];
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(key.getBytes("UTF-8"));
    System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

    Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);

    return decrypted;
}

public static String generateEncKey() {
    int strLen = 16;
    char[] chars = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789".toCharArray();
    StringBuilder sb = new StringBuilder();
    Random random = new SecureRandom();
    for (int i = 0; i < strLen; i++) {
        char c = chars[random.nextInt(chars.length)];
        sb.append(c);
    }
    return sb.toString();
}

运行代码时,出现以下错误-javax.crypto.BadPaddingException:给定最后一个块,未正确填充。如果在解密过程中使用了错误的密钥,则会出现此类问题。

但是,我可以加密和解密文件而无需拆分和合并。

所以我想知道我无法加密每个分割部分然后解密的代码有什么问题。

0 个答案:

没有答案