com.github.isaichkindanila.crypt.lib.file.FileEncryptor Maven / Gradle / Ivy
Show all versions of crypt-lib Show documentation
package com.github.isaichkindanila.crypt.lib.file;
import com.github.isaichkindanila.crypt.lib.cipher.StandardStreamCipher;
import com.github.isaichkindanila.crypt.lib.stream.EncryptedOutputStream;
import com.github.isaichkindanila.crypt.lib.util.IOUtils;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* Class used to encrypt files.
*
* @see FileDecryptor
*/
@SuppressWarnings("WeakerAccess")
public class FileEncryptor {
/**
* Extension of encrypted files.
*/
public static final String FILE_EXTENSION = "crypt";
private final IOHandler ioHandler;
private final OutputStream out;
private final List fileWrappers;
private long total;
/**
* @param file file or directory that will be encrypted
* @param targetDir directory where encrypted file will be put
* @param targetName name (without extension) of encrypted file
* @param cipher stream cipher to be used to encrypt files
* @param password password to be used to encrypt files
* @throws IOException if IOException occurs while writing stream header
* @throws IllegalArgumentException if file to be encrypted does not exist
*/
public FileEncryptor(File file,
File targetDir,
String targetName,
StandardStreamCipher cipher,
String password) throws IOException {
if (!file.exists()) {
throw new IllegalArgumentException("file does not exist");
}
if (!targetDir.exists() && !targetDir.mkdirs()) {
throw new FileNotFoundException("directory '" + targetDir.getAbsolutePath() + "' does not exist and cannot be created");
}
File target = new File(targetDir, targetName + "." + FILE_EXTENSION);
OutputStream fileOut = new FileOutputStream(target);
OutputStream buffered = new BufferedOutputStream(fileOut);
out = new EncryptedOutputStream(buffered, cipher, password);
ioHandler = new IOHandler();
fileWrappers = new ArrayList<>();
total = createWrappers(file, "");
}
/**
* Uses {@link StandardStreamCipher#ChaCha8 ChaCha8} stream cipher to encrypt files.
*
* @param file file or directory that will be encrypted
* @param targetDir directory where encrypted file will be put
* @param targetName name (without extension) of encrypted file
* @param password password to be used to encrypt files
* @throws IOException if IOException occurs while writing stream header
*/
public FileEncryptor(File file, File targetDir, String targetName, String password) throws IOException {
this(file, targetDir, targetName, StandardStreamCipher.ChaCha8, password);
}
/**
* Encrypted file name will be concatenation of original file name, a dot and {@link #FILE_EXTENSION}.
*
* @param file file or directory that will be encrypted
* @param targetDir directory where encrypted file will be put
* @param cipher stream cipher to be used to encrypt files
* @param password password to be used to encrypt files
* @throws IOException if IOException occurs while writing stream header
*/
public FileEncryptor(File file, File targetDir, StandardStreamCipher cipher, String password) throws IOException {
this(file, targetDir, file.getName(), cipher, password);
}
/**
* Uses {@link StandardStreamCipher#ChaCha8 ChaCha8} stream cipher to encrypt files.
*
* Encrypted file name will be concatenation of original file name, a dot and {@link #FILE_EXTENSION}.
*
* @param file file or directory that will be encrypted
* @param targetDir directory where encrypted file will be put
* @param password password to be used to encrypt files
* @throws IOException if IOException occurs while writing stream header
*/
public FileEncryptor(File file, File targetDir, String password) throws IOException {
this(file, targetDir, file.getName(), password);
}
private long createWrappers(File file, String path) {
if (file.isDirectory()) {
File[] children = file.listFiles();
long size = 0;
if (children != null) {
path += file.getName() + "/";
for (File f : children) {
size += createWrappers(f, path);
}
}
return size;
} else {
fileWrappers.add(new FileWrapper(file, path + file.getName()));
return file.length();
}
}
private void encrypt(FileWrapper wrapper) throws IOException {
IOUtils.writeByteArray(wrapper.path.getBytes(StandardCharsets.UTF_8), out);
IOUtils.writeLong(wrapper.file.length(), out);
ioHandler.copy(wrapper.file, out);
}
/**
* Encrypts file or directory passed in constructor.
*
* @throws IOException if IOException occurs
*/
public void encrypt() throws IOException {
IOUtils.writeLong(total, out);
IOUtils.writeInt(fileWrappers.size(), out);
for (FileWrapper wrapper : fileWrappers) {
encrypt(wrapper);
}
out.close();
}
/**
* Returns value in range [0, 1] representing encryption progress,
* where 0 means "not started yet" and 1 means "already finished".
*
* @return double value in range [0, 1]
*/
public double progress() {
return total == 0 ? 1.0 : 1.0 * ioHandler.done / total;
}
private static class FileWrapper {
private final File file;
private final String path;
private FileWrapper(File file, String path) {
this.file = file;
this.path = path;
}
}
}