diff --git a/app/src/main/java/lightcontainer/protocol/rules/reader/SavefileRule.java b/app/src/main/java/lightcontainer/protocol/rules/reader/SavefileRule.java index 444a916..50a7f91 100644 --- a/app/src/main/java/lightcontainer/protocol/rules/reader/SavefileRule.java +++ b/app/src/main/java/lightcontainer/protocol/rules/reader/SavefileRule.java @@ -5,10 +5,12 @@ 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 java.io.IOException; import java.io.InputStream; +import java.security.NoSuchAlgorithmException; public class SavefileRule extends ProtocolReader { // Constants @@ -41,12 +43,18 @@ public class SavefileRule extends ProtocolReader { System.out.printf("Sauvegarde du fichier : %s %d\n", filename, size); try { - FileReceiver fileReceiver = new FileReceiver("/home/benjamin/ffe"); // "D:\\"); - if (!fileReceiver.receiveFile(reader, this.filename, this.size)) + FileReceiver fileReceiver = new FileReceiver("D:\\"); //"/home/benjamin/ffe"); + + String key = AES_GCM.generateSecretKey(); + String iv = AES_GCM.generateIV(); + System.out.println("Clé " + key); + System.out.println("IV " + iv); + + if (!fileReceiver.receiveFile(reader, this.filename, this.size, key, iv)) throw new IOException(); this.setResultCommand(protocolRep.executeWriter(SendfileRule.NAME, this.filename, String.valueOf(this.size), "EMPREINTEBLBLBLBLBLABLABLBALBALBALBALBALBALBALBALBALABLBALBALBALABLABLABLABLABLABLABALBLABALABLABLABLABKJABKAHBHKBHJbhjvgkh"), ResultCmdReceiver.STOREBACKEND); - } catch (IOException e) { + } catch (IOException | AES_GCM.AesGcmException e) { this.setResultCommand(protocolRep.executeWriter(SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT); e.printStackTrace(); } diff --git a/app/src/main/java/lightcontainer/protocol/rules/writer/SendfileRule.java b/app/src/main/java/lightcontainer/protocol/rules/writer/SendfileRule.java index be51736..c12ddb9 100644 --- a/app/src/main/java/lightcontainer/protocol/rules/writer/SendfileRule.java +++ b/app/src/main/java/lightcontainer/protocol/rules/writer/SendfileRule.java @@ -36,7 +36,7 @@ public class SendfileRule extends ProtocolWriter { public void write(OutputStream writer) { super.write(writer); System.out.println("Envoie du fichier au SBE"); - FileSender fileSender = new FileSender("/home/benjamin/ffe"); + FileSender fileSender = new FileSender("D:\\"); //"/home/benjamin/ffe"); fileSender.sendFile(hashedFileName, writer); } } diff --git a/app/src/main/java/lightcontainer/utils/AES_GCM.java b/app/src/main/java/lightcontainer/utils/AES_GCM.java index 2a9c832..09c03c6 100644 --- a/app/src/main/java/lightcontainer/utils/AES_GCM.java +++ b/app/src/main/java/lightcontainer/utils/AES_GCM.java @@ -1,14 +1,21 @@ package lightcontainer.utils; -import javax.crypto.Cipher; -import javax.crypto.KeyGenerator; -import javax.crypto.SecretKey; +import javax.crypto.*; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.security.*; import java.util.Base64; +/** + * AES GCM 256 Encryption Class [DO NOT EDIT] + * + * @since 1.0 + * @version 1.0 + * + * @author Jérémi Nihart + */ public class AES_GCM { // Constants public static final int AES_KEY_SIZE = 256; @@ -17,35 +24,82 @@ public class AES_GCM { public static void main(String[] args) throws Exception { - // Text pour test : - String plainText = "salut fils de pute";//TODO enlever le text chelou de Jérémi (ce fou là) + /* + * FILE ENCRYPTION DEMO + */ + // Init files + File inFile = new File("D:\\HELMo.png"); + File outFile = new File("D:\\HELMoCrypted.png"); + File clearFile = new File("D:\\HELMoClear.png"); + outFile.createNewFile(); + clearFile.createNewFile(); + // Make options + String IVFile = generateIV(); + String keyFile = generateSecretKey(); + // Show options + System.out.println("IV : "+IVFile); + System.out.println("Key : "+keyFile); + // Encrypt + encryptStream( + new FileInputStream(inFile), + new FileOutputStream(outFile), + IVFile, + keyFile + ); + // Decrypt + decryptStream( + new FileInputStream(outFile), + new FileOutputStream(clearFile), + IVFile, + keyFile + ); + /* + * TEXT ENCRYPTION DEMO + */ + // Make option + String plainText = "Salut sombre fils de pute, comment vas tu ?";//TODO enlever le text chelou de Jérémi (ce fou là) String IV = generateIV(); String key = generateSecretKey(); - - System.out.println("Original Text : " + plainText); - - byte[] cipherText = encrypt(plainText.getBytes(), key, IV); - System.out.println("Encrypted Text : " + Base64.getEncoder().encodeToString(cipherText)); - - String decryptedText = decrypt(cipherText, key, IV); - System.out.println("DeCrypted Text : " + decryptedText); + // Show options + System.out.println("IV : "+IV); + System.out.println("Key : "+key); + System.out.println("Original text : " + plainText); + // Crypt + String cryptText = encrypt(plainText, key, IV); + System.out.println("Encrypted text : " + cryptText); + // Decrypt + String decryptedText = decrypt(cryptText, key, IV); + System.out.println("Decrypted text : " + decryptedText); } /** * Decoder to decode base64 vector to byte vector. - * @param base64Vector A base64 encoded vector. - * @return Byte vector. + * + * @param base64Vector A base64 encoded vector. + * @return Byte vector. */ - private static byte[] decodeBase64(String base64Vector) { + private static byte[] decodeBase64Vector(String base64Vector) { Base64.Decoder b64Decoder = Base64.getDecoder(); return b64Decoder.decode(base64Vector); } + /** + * Decoder to decode base64 string to plain string. + * + * @param base64String A base64 encoded string. + * @return Plain string. + * + * @see AES_GCM#decodeBase64Vector(String) + */ + private static String decodeBase64String(String base64String) { + return new String(decodeBase64Vector(base64String)); + } + /** * Encoder to encode vector to base64 string. - * @param rawVector A raw vector. - * @return A base64 encoded vector. + * @param rawVector A raw vector. + * @return A base64 encoded vector. */ private static String encodeBase64(byte[] rawVector) { Base64.Encoder b64Encoder = Base64.getEncoder(); @@ -53,19 +107,66 @@ public class AES_GCM { } /** - * Generate a secret key base64 encoded. - * @return New Secret key b64 encoded. + * Encoder to encode string to base64 string. + * @param rawString A raw string. + * @return A base64 encoded string. + * + * @see AES_GCM#encodeBase64(byte[])) */ - public static String generateSecretKey() throws NoSuchAlgorithmException { - KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); - keyGenerator.init(AES_KEY_SIZE); - SecretKey key = keyGenerator.generateKey(); - return encodeBase64(key.getEncoded()); + private static String encodeBase64(String rawString) { + return encodeBase64(rawString.getBytes(StandardCharsets.UTF_8)); + } + + /** + * FACTORY, to setting up a Java cryptographic cypher. + * + * @param op_mode the operation mode of this cipher (this is one of the + * following: ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE or UNWRAP_MODE) + * @param key Base64 encoded secret key. + * @param IV Base64 encoded vector. + * + * @return A Cryptography cypher. + * + * @throws AesGcmException Throw an exception in case of an error occur while setting up the the cypher. + */ + private static Cipher createCipher(int op_mode, String key, String IV) throws AesGcmException { + try { + // Get a cipher instance + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + // Create a secret key from the key for the specific crypto algo + SecretKeySpec keySpec = new SecretKeySpec(decodeBase64Vector(key), "AES"); + // Create a GCMParameterSpec to setting up the AES init vector + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, decodeBase64Vector(IV)); + // Init the cipher for the selected operation + cipher.init(op_mode, keySpec, gcmParameterSpec); + return cipher; + } catch (InvalidAlgorithmParameterException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) { + throw new AesGcmException(e, "Error while creating the Cipher object"); + } + } + + /** + * Generate a secret key base64 encoded. + * + * @return New Secret key b64 encoded. + * + * @throws AesGcmException Exception if an error occur. + */ + public static String generateSecretKey() throws AesGcmException { + try { + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + keyGenerator.init(AES_KEY_SIZE); + SecretKey key = keyGenerator.generateKey(); + return encodeBase64(key.getEncoded()); + } catch (NoSuchAlgorithmException e) { + throw new AesGcmException("Error while generating the AES secret key"); + } } /** * Generate an IV (initialisation vector) base64 encoded. - * @return New generated IV b64 encoded. + * + * @return New generated IV b64 encoded. */ public static String generateIV() { byte[] IV = new byte[GCM_IV_LENGTH]; @@ -75,52 +176,146 @@ public class AES_GCM { } /** - * Encrypt, with AES GCM. - * @param plainContent Content to encrypt. - * @param key Base64 encoded secret key. - * @param IV Base64 encoded vector. - * @return The encrypted cipherContent. + * Encrypt text, with AES GCM. + * + * @param plainText Plain text to encrypt. + * @param key Base64 encoded secret key. + * @param IV Base64 encoded vector. + * + * @return The encrypted plain text Base64 encoded. + * + * @throws AesGcmException Exception if an error occur. */ - public static byte[] encrypt(byte[] plainContent, String key, String IV) throws Exception - { - // Get Cipher Instance - Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + public static String encrypt(String plainText, String key, String IV) throws AesGcmException { + try { + // Make the cipher for encryption + Cipher cipher = createCipher(Cipher.ENCRYPT_MODE, key, IV); + // Perform Encryption + return encodeBase64(cipher.doFinal(plainText.getBytes())); + } catch (Exception e) { + throw new AesGcmException(e); + } + } - // Create SecretKeySpec - SecretKeySpec keySpec = new SecretKeySpec(decodeBase64(key), "AES"); - - // Create GCMParameterSpec - GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, decodeBase64(IV)); - - // Initialize Cipher for ENCRYPT_MODE - cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec); - - // Perform Encryption - return cipher.doFinal(plainContent); + /** + * Encrypt stream, with AES GCM. + * + * @param in InputStream to the input, flux to encrypt. + * @param out OutputStream to the output, encrypted flux. + * @param key Base64 encoded secret key. + * @param IV Base64 encoded vector. + * + * @throws AesGcmException Exception if an error occur. + */ + private static void encryptStream(InputStream in, OutputStream out, String key, String IV) throws AesGcmException { + byte[] buffer = new byte[1024]; + int bytes; + try { + // Make the cipher for encryption + Cipher cipher = createCipher(Cipher.ENCRYPT_MODE, key, IV); + // Initialize a CipherOutputStream + CipherOutputStream cipherOut = new CipherOutputStream(out, cipher); + // Encryption Process + while((bytes = in.read(buffer)) > 0) { + cipherOut.write(buffer, 0, bytes); + cipherOut.flush(); + } + // Close CipherOutputStream + cipherOut.close(); + } catch (Exception e) { + throw new AesGcmException(e); + } } /** * Decrypt, with AES GCM. - * @param cipherContent The encrypted cipherContent - * @param key Base64 encoded secret key. - * @param IV Base64 encoded vector. - * @return The decrypted plainContent. + * + * @param cryptText The encrypted text. + * @param key Base64 encoded secret key. + * @param IV Base64 encoded vector. + * + * @return The decrypted plain text. + * + * @throws AesGcmException Exception if an error occur. */ - public static String decrypt(byte[] cipherContent, String key, String IV) throws Exception - { - // Get Cipher Instance - Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + public static String decrypt(String cryptText, String key, String IV) throws AesGcmException { + try { + // Make the cipher for decryption + Cipher cipher = createCipher(Cipher.DECRYPT_MODE, key, IV); + // Perform Decryption + return new String(cipher.doFinal(decodeBase64Vector(cryptText))); + } catch (Exception e) { + throw new AesGcmException(e); + } + } - // Create SecretKeySpec - SecretKeySpec keySpec = new SecretKeySpec(decodeBase64(key), "AES"); + /** + * Decrypt stream, with AES GCM. + * + * @param in InputStream to the input, flux to decrypt. + * @param out OutputStream to the output, decrypted flux. + * @param key Base64 encoded secret key. + * @param IV Base64 encoded vector. + * + * @throws AesGcmException Exception if an error occur. + */ + private static void decryptStream(InputStream in, OutputStream out, String key, String IV) throws AesGcmException { + byte[] buffer = new byte[1024]; + int bytes; + try { + // Make the cipher for decryption + Cipher cipher = createCipher(Cipher.DECRYPT_MODE, key, IV); + // Initialize a CipherOutputStream + CipherInputStream cipherIn = new CipherInputStream(in, cipher); + // Encryption Process + while((bytes = cipherIn.read(buffer)) > 0) { + out.write(buffer, 0, bytes); + out.flush(); + } + // Close CipherOutputStream + cipherIn.close(); + } catch (Exception e) { + throw new AesGcmException(e); + } + } - // Create GCMParameterSpec - GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH*8, decodeBase64(IV)); + /** + * Internal Error from AES_GCM encryption Class + */ + public static class AesGcmException extends Exception { + private static final long serialVersionUID = -145972354893514657L; + /** + * Constructor of AesGcmException, + * which define it's own detail message. + * + * @param msg The detail message. + */ + public AesGcmException(String msg) { + super(msg); + } - // Initialize Cipher for DECRYPT_MODE - cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec); + /** + * Constructor of AesGcmException, + * which propagates the error triggering + * a crash of the encryption system. + * + * @param e Previous exception throwable. + */ + public AesGcmException(Throwable e) { + super(e); + } - // Perform Decryption - return new String(cipher.doFinal(cipherContent)); + /** + * Constructor of AesGcmException, + * which propagates the error triggering + * a crash of the encryption system with + * a chosen detail message. + * + * @param e Previous exception throwable. + * @param msg The detail message. + */ + public AesGcmException(GeneralSecurityException e, String msg) { + super(msg, e); + } } } \ No newline at end of file diff --git a/app/src/main/java/lightcontainer/utils/FileReceiver.java b/app/src/main/java/lightcontainer/utils/FileReceiver.java index c59452f..07f5a3f 100644 --- a/app/src/main/java/lightcontainer/utils/FileReceiver.java +++ b/app/src/main/java/lightcontainer/utils/FileReceiver.java @@ -1,7 +1,9 @@ package lightcontainer.utils; +import javax.crypto.Cipher; import java.io.BufferedOutputStream; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; public class FileReceiver { @@ -10,24 +12,19 @@ public class FileReceiver { public FileReceiver(String path) { this.path = path; } - public boolean receiveFile(InputStream input, String fileName, long fileSize) { + public boolean receiveFile(InputStream input, String fileName, long fileSize, String key, String iv) { int bytesReceived = 0; BufferedOutputStream bosFile = null; try { - byte[] buffer = new byte[DEFAULT_BUFFER]; bosFile = new BufferedOutputStream(new FileOutputStream(String.format("%s/%s", path, fileName))); - long currentOffset = 0; - while((currentOffset < fileSize) && ((bytesReceived = input.read(buffer)) > 0)) { - bosFile.write(buffer, 0, bytesReceived); - currentOffset += bytesReceived; - } + //AES_GCM.encryptStream(input, bosFile, fileSize, key, iv); + bosFile.flush(); bosFile.close(); - return true; - } catch(Exception ex) { + } catch(IOException ex) { ex.printStackTrace(); if(bosFile != null) { try { bosFile.close(); } catch(Exception e) {} } return false; diff --git a/app/src/main/java/lightcontainer/utils/FileSender.java b/app/src/main/java/lightcontainer/utils/FileSender.java index 92f93f3..b81fda5 100644 --- a/app/src/main/java/lightcontainer/utils/FileSender.java +++ b/app/src/main/java/lightcontainer/utils/FileSender.java @@ -10,19 +10,15 @@ public class FileSender { public boolean sendFile(String filename, OutputStream out) { BufferedInputStream bisFile = null; - int bytesReaded = 0; try { File f = new File(String.format("%s/%s", path, filename)); long fileSize = f.length(); if(f.exists()) { - byte[] buffer = new byte[DEFAULT_BUFFER]; bisFile = new BufferedInputStream(new FileInputStream(f)); - long currentOffset = 0; - while((currentOffset < fileSize) && (bytesReaded = bisFile.read(buffer)) > 0) { - out.write(buffer, 0, bytesReaded); out.flush(); - currentOffset+= bytesReaded; - } + + //AES_GCM.encryptStream(bisFile, out, fileSize, "hyjFrdMJW6Pur8fiFueVrWKqwtnqAZmXEZPBAyBXp+o=", "e6H7xuw+PNrDppJCPLTKhg=="); + bisFile.close(); return true; } else