Java 如何加密分割文件的每个部分
我有一个类可以将给定的文件拆分并合并为多个文件,但我想知道如何在拆分时加密每个文件,然后在再次合并时解密 这是用于文件拆分和合并的类Java 如何加密分割文件的每个部分,java,file,encryption,file-io,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 fileNam
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 void splitFile(文件f)引发异常{
int partCounter=1;
int sizeofficeles=(int)(f.length()/3);
字节[]缓冲区=新字节[sizeOfFiles];
字符串文件名=f.getName();
String destFileName=fileName.substring(0,fileName.lastIndexOf('.')+“+”+FilenameUtils.getExtension(fileName);
try(FileInputStream fis=newfileinputstream(f);
BufferedInputStream bis=新的BufferedInputStream(fis)){
int字节数=0;
而((字节数=bis.read(buffer))>0){
String filePartName=String.format(“%s.%03d”,destFileName,partCounter++);
File newFile=新文件(“D:\\FileTest\\”,filePartName);
try(FileOutputStream out=newfileoutputstream(newFile)){
//我想这就是在写入文件之前加密每个分割部分的方法?
out.write(FileEncrypt.encrypt(buffer,encKey),0,bytesAmount);
}
}
bos.close();
}
}
公共列表ListOfficeStorege(文件oneOfFiles)引发IOException,Exception{
字符串tmpName=oneofiles.getName();
字符串destFileName=tmpName.substring(0,tmpName.lastIndexOf('.');
File[]files=oneofficefiles.getParentFile().listFiles((文件目录,字符串名称)->name.matches(destFileName+“[.]\\d+”);
数组。排序(文件);
用于(文件f:文件){
//这就是如何在文件合并之前解密文件?
FileEncrypt.decrypt(Files.readAllBytes(f.toPath()),encKey);
}
返回Arrays.asList(文件);
}
公共void合并文件(列出文件、文件到)引发异常{
try(FileOutputStream fos=新的FileOutputStream(into);
BufferedOutputStream mergingStream=新的BufferedOutputStream(fos)){
用于(文件f:文件){
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();
}
公共静态字节[]加密(字节[]字节,字符串密钥)引发异常{
字节[]iv=新字节[ivSize];
SecureRandom=新的SecureRandom();
随机。下一字节(iv);
IvParameterSpec IvParameterSpec=新的IvParameterSpec(iv);
MessageDigest=MessageDigest.getInstance(“SHA-256”);
更新(key.getBytes(“UTF-8”);
byte[]keyBytes=新字节[keySize];
System.arraycopy(digest.digest(),0,keyBytes,0,keyBytes.length);
SecretKeySpec SecretKeySpec=新SecretKeySpec(keyBytes,“AES”);
Cipher Cipher=Cipher.getInstance(“AES/CBC/PKCS5Padding”);
cipher.init(cipher.ENCRYPT_模式、secretKeySpec、ivParameterSpec);
字节[]加密=cipher.doFinal(字节);
byte[]encryptedIVAndFile=新字节[ivSize+encrypted.length];
System.arraycopy(iv,0,EncryptedInvandFile,0,ivSize);
System.arraycopy(加密,0,EncryptedInvandFile,ivSize,encrypted.length);
返回加密文件;
}
公共静态字节[]解密(字节[]encryptedIvFileBytes,字符串密钥)引发异常{
字节[]iv=新字节[ivSize];
System.arraycopy(encryptedIvFileBytes,0,iv,0,iv.length);
IvParameterSpec IvParameterSpec=新的IvParameterSpec(iv);
int encryptedSize=encryptedIvFileBytes.length-ivSize;
字节[]encryptedBytes=新字节[encryptedSize];
System.arraycopy(encryptedIvFileBytes,ivSize,encryptedBytes,0,encryptedSize);
byte[]keyBytes=新字节[keySize];
MessageDigest md=MessageDigest.getInstance(“SHA-256”);
md.update(key.getBytes(“UTF-8”);
arraycopy(md.digest(),0,keyBytes,0,keyBytes.length);
SecretKeySpec SecretKeySpec=新SecretKeySpec(keyBytes,“AES”);
Cipher cipherDecrypt=Cipher.getInstance(“AES/CBC/PKCS5Padding”);
cipherDecrypt.init(Cipher.DECRYPT_模式,secretKeySpec,ivParameterSpec);
byte[]decrypted=cipherDecrypt.doFinal(encryptedBytes);
返回解密;
}
公共静态字符串generateEncKey(){
int strLen=16;
char[]chars=“abcdefghjkmnpqrstuvxyzabefghjkmnpqrstuvxyz23456789”。tocharray();
StringBuilder sb=新的StringBuilder();
Random Random=新的SecureRandom();
对于(int i=0;i
当我运行代码时,我得到了-javax.crypto.BadPaddingException错误:给定的最后一个块没有正确填充。如果在解密过程中使用了坏密钥,则可能会出现此类问题
然而,我可以加密和解密一个文件,而无需拆分和合并
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);
}
}
}
所以我想知道我不能加密每个分割部分然后解密的代码有什么问题。
bis.read(buffer)
不能保证读取那么多字节,即使是可用的。如果先分割然后加密,那么最好先解密然后合并。第一次合并是可能的,但是您需要知道拆分发生在哪里,因为您只能解密在CBC模式下加密的相同部分。