Ajout système de suppression en profondeur + hash file content.

This commit is contained in:
Jérémi N ‘EndMove’ 2022-03-19 17:34:15 +01:00
parent f87c81aba4
commit 3ce850e04c
Signed by: EndMove
GPG Key ID: 65C4A02E1F5371A4
12 changed files with 193 additions and 48 deletions

View File

@ -67,7 +67,7 @@ public class App {
protocolRep.addWriter(new SaveFileOkRule(repositoryStorage.getStoragePath()));
protocolRep.addWriter(new SaveFileErrorRule(repositoryStorage.getStoragePath()));
protocolRep.addWriter(new SendfileRule(repositoryStorage.getStoragePath()));
protocolRep.addWriter(new GetFileErrorRule());
protocolRep.addWriter(new GetFileErrorRule(repositoryStorage.getStoragePath()));
protocolRep.addWriter(new EraseFileRule());
protocolRep.addWriter(new RemoveFileErrorRule());
protocolRep.addWriter(new RemoveFileOkRule());

View File

@ -47,7 +47,7 @@ public class FilelistRule extends ProtocolReader {
return result;
}
@Override
@Override//TODO ???
protected <T extends ProtocolResult> T onError(Context context) {
return super.onError(context);
}

View File

@ -38,7 +38,6 @@ public class RemoveFileRule extends ProtocolReader {
}
}
@Override
protected RemoveFileRule.Result onExecuted(Context context, String... data) {
RemoveFileRule.Result result = new RemoveFileRule.Result(context, data[FILENAME]);

View File

@ -3,10 +3,10 @@ package lightcontainer.protocol.rules.reader;
import lightcontainer.domains.client.Context;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.rules.writer.GetFileErrorRule;
import lightcontainer.protocol.rules.writer.GetFileOkRule;
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
import lightcontainer.utils.FileReceiver;
import lightcontainer.utils.FileSender;
import lightcontainer.utils.SHA;
import java.io.InputStream;
@ -59,11 +59,17 @@ public class RetrieveOkRule extends ProtocolReader {
public void read(InputStream reader) {
super.read(reader);
System.out.println("Récupération du fichier du SBE");
FileReceiver fileReceiver = new FileReceiver(storagePath);
fileReceiver.receiveFile(reader, this.filename, this.filesize);
// TODO fingerprint <!!!!!!>
try {
FileReceiver fileReceiver = new FileReceiver(storagePath);
if (!fileReceiver.receiveFile(reader, this.filename, this.filesize)) {
throw new IllegalStateException("Bad file reception");
}
if (SHA.hashFile(storagePath, this.filename).equals(this.hashedFileContent)) {
throw new IllegalStateException("File hash content are not equals");
}
} catch (IllegalStateException|SHA.ShaException e) {
this.setResultCommand(protocolRep.executeWriter(getContext(), GetFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
}
}
}
@ -89,7 +95,7 @@ public class RetrieveOkRule extends ProtocolReader {
@Override
protected ProtocolReader.ProtocolResult onError(Context context) {
ProtocolResult result = new ProtocolResult(context);
result.setResultCommand(protocolRep.executeWriter(context, SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
result.setResultCommand(protocolRep.executeWriter(context, GetFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
return result;
}
}

View File

@ -6,10 +6,7 @@ import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
import lightcontainer.protocol.rules.writer.SendfileRule;
import lightcontainer.utils.AES_GCM;
import lightcontainer.utils.FileReceiver;
import lightcontainer.utils.SHA;
import lightcontainer.utils.ShaHasher;
import lightcontainer.utils.*;
import java.io.File;
import java.io.IOException;
@ -85,10 +82,7 @@ public class SavefileRule extends ProtocolReader {
this.setResultCommand(protocolRep.executeWriter(getContext(), SendfileRule.NAME, this.filename, String.valueOf(encryptedFileSize), fileHash), ResultCmdReceiver.STOREBACKEND);
} catch (IOException | SHA.ShaException e) {
// TODO : Supprimer le fichier
System.out.println("HEYHEYHEYHEYHEY OHOHOH");
this.setResultCommand(protocolRep.executeWriter(getContext(), SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
e.printStackTrace();
}
} else {
this.setResultCommand(protocolRep.executeWriter(getContext(), SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);

View File

@ -5,10 +5,6 @@ import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Règle permettant de de confirmer la sauvegrade d'un fichier.
*/
@ -27,12 +23,10 @@ public class SendOkRule extends ProtocolReader {
this.protocolRep = protocolRep;
}
@Override
protected ProtocolResult onExecuted(Context context, String... data) {
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult(context);
result.setResultCommand(protocolRep.executeWriter(context, SaveFileOkRule.NAME), ResultCmdReceiver.CLIENT);
return result;
}
}

View File

@ -1,6 +1,8 @@
package lightcontainer.protocol.rules.writer;
import lightcontainer.domains.client.Context;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.utils.DeepFileEraser;
/**
* Règle utilisé dans le cas ou une erreur survient lors
@ -11,8 +13,22 @@ public class GetFileErrorRule extends ProtocolWriter {
private static final String PATTERN = "^GETFILE_ERROR\r\n$";
public static final String NAME = "GETFILE_ERROR";
// Variables
private final String storagePath;
// Constructors
public GetFileErrorRule() {
public GetFileErrorRule(String storagePath) {
super(NAME, PATTERN);
this.storagePath = storagePath;
}
@Override
protected ProtocolResult onExecuted(Context context, String... data) {
// Delete the file
try {
DeepFileEraser.eraseFile(String.format("%s/%s", storagePath, context.getDataString("hashedFileName")));
} catch (DeepFileEraser.DeepFileEraserException ignore) { }
// Return new protocol result
return new ProtocolResult(context);
}
}

View File

@ -2,12 +2,11 @@ package lightcontainer.protocol.rules.writer;
import lightcontainer.domains.client.Context;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.utils.DeepFileEraser;
import lightcontainer.utils.FileSender;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
public class GetFileOkRule extends ProtocolWriter {
// Constants
@ -46,7 +45,6 @@ public class GetFileOkRule extends ProtocolWriter {
public void write(OutputStream writer) throws IOException {
System.out.printf("Sauvegarde du fichier : %s %d\n", this.filename, this.filesize);
System.out.println("Encrypted size for parsing: " + getContext().getDataInt("encryptedFileSize")+" normal: "+getContext().getDataInt("fileSize"));
FileSender fileSender = new FileSender(storagePath);
fileSender.sendFile(
getContext().getDataString("hashedFileName"),
@ -57,8 +55,8 @@ public class GetFileOkRule extends ProtocolWriter {
);
try {
Files.deleteIfExists(Path.of(String.format("%s/%s", storagePath, getContext().getDataString("hashedFileName"))));
} catch (IOException ignore) { }
DeepFileEraser.eraseFile(String.format("%s/%s", storagePath, getContext().getDataString("hashedFileName")));
} catch (DeepFileEraser.DeepFileEraserException ignore) { }
}
}

View File

@ -2,12 +2,9 @@ package lightcontainer.protocol.rules.writer;
import lightcontainer.domains.client.Context;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.utils.DeepFileEraser;
import lightcontainer.utils.ShaHasher;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Règle signifiant que la sauvegarde d'un fichier a échoué
*/
@ -32,13 +29,9 @@ public class SaveFileErrorRule extends ProtocolWriter {
// Suppression du fichier temporaire dans le stockage du FFE
ShaHasher hasher = new ShaHasher(context.getLogin() + "_" + context.getDataString("fileName"));
try {
Files.deleteIfExists(Path.of(
String.format("%s/%s", this.storagePath,
hasher.fromSalt(hasher.saltToByte(context.getDataString("fileNameSalt")))
)
));
} catch (IOException e) {}
DeepFileEraser.eraseFile(String.format("%s/%s", this.storagePath,
hasher.fromSalt(hasher.saltToByte(context.getDataString("fileNameSalt")))));
} catch (DeepFileEraser.DeepFileEraserException ignore) { }
return result;
}
}

View File

@ -2,10 +2,7 @@ package lightcontainer.protocol.rules.writer;
import lightcontainer.domains.client.Context;
import lightcontainer.protocol.ProtocolWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import lightcontainer.utils.DeepFileEraser;
/**
* Règle signifiant que la sauvegarde d'un fichier fût un succès
@ -32,9 +29,10 @@ public class SaveFileOkRule extends ProtocolWriter {
// Suppression du fichier temporaire dans le stockage du FFE
String hashedFileName = context.getHashedFileName(context.getDataString("fileName"));
try {
Files.deleteIfExists(Path.of(String.format("%s/%s", storagePath, hashedFileName)));
} catch (IOException ignore) {}
DeepFileEraser.eraseFile(String.format("%s/%s", storagePath, hashedFileName));
} catch (DeepFileEraser.DeepFileEraserException ignore) { }
return result;
}
}

View File

@ -0,0 +1,148 @@
package lightcontainer.utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Arrays;
/**
* DeepFileEraser - Secure file remover
*
* @since 1.0
* @version 1.0
*
* @author Jérémi Nihart <contact@endmove.eu>
*/
public class DeepFileEraser {
public static final int DFE_BUFFER_DEFAULT_SIZE = 1024; // Default buffer size
public static final int DFE_BUFFER_MINIMUM_SIZE = 250; // Minimum buffer size
public static final int DFE_BASE_DEFAULT_FILL_VALUE = 0; // Filling value of the initialisation phase
public static final int DFE_STEP_MIN_FILL_VALUE = 0; // Minimum filling value of a writing phase
public static final int DFE_STEP_MAX_FILL_VALUE = 15; // Maximum filling value of a writing phase
public static void main(String[] args) throws Exception
{
System.out.println(random(1, 3));
try {
eraseFile("D:\\lol");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Generate a number randomly.
*
* @param min Minimal value (included)
* @param max Maximal value (included)
*
* @return Random generated number.
*/
private static int random(int min, int max) {
return min + (int)(Math.random() * ((max - min) + 1));
}
/**
* Simple remove operation.
*
* @param target File object on which to operate.
* @param length File size.
*
* @throws DeepFileEraserException Exception if an error occur.
*/
private static void eraseBase(File target, long length) throws DeepFileEraserException {
byte[] buffer = new byte[DFE_BUFFER_DEFAULT_SIZE];
long wroteLength = 0;
try (OutputStream out = new FileOutputStream(target)) {
Arrays.fill(buffer, (byte)DFE_BASE_DEFAULT_FILL_VALUE);
while (wroteLength < length) {
if (wroteLength + buffer.length > length) {
buffer = new byte[(int)(length-wroteLength)];
Arrays.fill(buffer, (byte)DFE_BASE_DEFAULT_FILL_VALUE);
}
out.write(buffer);
wroteLength += buffer.length;
}
} catch (Exception e) {
throw new DeepFileEraserException(e, "Error while the Base erasing step.");
}
}
/**
* Deep remove operation.
*
* @param target File object on which to operate.
* @param length File size.
*
* @throws DeepFileEraserException Exception if an error occur.
*/
private static void eraseStep(File target, long length) throws DeepFileEraserException {
byte[] buffer = new byte[random(DFE_BUFFER_MINIMUM_SIZE, DFE_BUFFER_DEFAULT_SIZE)];
long wroteLength = 0;
try (OutputStream out = new FileOutputStream(target)) {
while(wroteLength < length) {
if (wroteLength + buffer.length > length) buffer = new byte[(int)(length-wroteLength)];
Arrays.fill(buffer, (byte) random(DFE_STEP_MIN_FILL_VALUE, DFE_STEP_MAX_FILL_VALUE));
out.write(buffer);
wroteLength += buffer.length;
}
} catch (Exception e) {
throw new DeepFileEraserException(e, "Error while the Step erasing step.");
}
}
/**
* Erase a file deeply.
* default deeply level = 5.
*
* @param filePath Path of the file.
*
* @throws DeepFileEraserException Exception if an error occur.
*/
public static void eraseFile(String filePath) throws DeepFileEraserException {
eraseFile(filePath, 5);
}
/**
* Erase a file deeply.
*
* @param filePath Path of the file.
* @param depthLevel Erasure level (the higher the number, the longer and more secure the erasure).
*
* @throws DeepFileEraserException Exception if an error occur.
*/
public static void eraseFile(String filePath, int depthLevel) throws DeepFileEraserException {
// Init
File target = new File(filePath);
if (target.exists()) {
long targetSize = target.length();
// Base write
eraseBase(target, targetSize);
// Deep write
for (int i = 0; i < depthLevel; i++) eraseStep(target, targetSize);
// Delete file
target.delete();
}
}
/**
* Internal Error from DeepFileEraser encryption Class
*/
public static class DeepFileEraserException extends Exception {
// Constant
private static final long serialVersionUID = -158979547897543145L;
/**
* Constructor of DeepFileEraserException,
* which propagates the error triggering
* a crash of the erasing file system with
* a chosen detail message.
*
* @param e Previous exception throwable.
* @param msg The detail message.
*/
public DeepFileEraserException(Throwable e, String msg) {
super(msg, e);
}
}
}

View File

@ -115,5 +115,4 @@ public class SHA {
super(e);
}
}
}