methods = new ArrayList<>(encryptionMap.keySet());
+ Collections.reverse(methods);
+
+ for (String method : methods) {
+ switch (method) {
+ case "RotX" -> {
+ //decrypt json content from databases RotX encryptionmethod
+ int shift = Integer.parseInt(encryptionMap.get("RotX"));
+ result = ROTX.decryptROT(result, shift);
+ }
+ case "RC4" -> {
+ //decrypt json content from databases RC4 encryptionmethod
+
+ RC4 rc4 = new RC4();
+ String key = encryptionMap.get("RC4");
+ rc4.init(key);
+ result = rc4.decrypt(result);
+ }
+ case "Vigenere" -> {
+ //decrypt json content from databases Vigenere encryptionmethod
+
+ String key = encryptionMap.get("Vigenere");
+ result = VigenereAlgo.decrypt(result, key);
+ }
+ case "Polybios" -> {
+ }
+ case "AES" -> {
+ }
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/src/Classes/Steganography/Image.java b/src/Classes/Steganography/Image.java
new file mode 100644
index 0000000..77f0f1c
--- /dev/null
+++ b/src/Classes/Steganography/Image.java
@@ -0,0 +1,134 @@
+package Classes.Steganography;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+
+public class Image extends Steganography {
+ private BufferedImage image;
+ private String imagePath;
+
+ public Image(String imagePath) {
+ this.imagePath = imagePath;
+ try {
+ this.image = ImageIO.read(new File(imagePath));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void encode(String message) {
+ if (image == null || message == null) {
+ throw new IllegalArgumentException("Image or message is null");
+ }
+
+ // Add message length at the beginning
+ message = message.length() + ":" + message;
+
+ // Convert message to binary
+ byte[] messageBytes = message.getBytes();
+ int messageLength = messageBytes.length;
+
+ // Check if image can hold the message
+ if (messageLength * 8 > image.getWidth() * image.getHeight()) {
+ throw new IllegalArgumentException("Message too large for this image");
+ }
+
+ int messageIndex = 0;
+ int bitIndex = 0;
+
+ // Iterate through image pixels
+ for (int y = 0; y < image.getHeight() && messageIndex < messageLength; y++) {
+ for (int x = 0; x < image.getWidth() && messageIndex < messageLength; x++) {
+ int pixel = image.getRGB(x, y);
+
+ if (bitIndex == 8) {
+ messageIndex++;
+ bitIndex = 0;
+ }
+
+ if (messageIndex < messageLength) {
+ // Get current byte from message
+ byte currentByte = messageBytes[messageIndex];
+
+ // Get current bit from byte
+ int messageBit = (currentByte >> (7 - bitIndex)) & 1;
+
+ // Modify blue channel
+ int blue = pixel & 0xff;
+ blue = (blue & 0xfe) | messageBit;
+
+ // Update pixel
+ pixel = (pixel & 0xffffff00) | blue;
+ image.setRGB(x, y, pixel);
+
+ bitIndex++;
+ }
+ }
+ }
+
+ // Save encoded image
+ try {
+ String outputPath = imagePath.substring(0, imagePath.lastIndexOf('.')) + "_encoded.png";
+ ImageIO.write(image, "png", new File(outputPath));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public String decode() {
+ if (image == null) {
+ throw new IllegalArgumentException("No image loaded");
+ }
+
+ StringBuilder binary = new StringBuilder();
+ StringBuilder message = new StringBuilder();
+ int count = 0;
+
+ // First, extract the message length
+ StringBuilder lengthStr = new StringBuilder();
+ boolean foundDelimiter = false;
+
+ outer:
+ for (int y = 0; y < image.getHeight(); y++) {
+ for (int x = 0; x < image.getWidth(); x++) {
+ int pixel = image.getRGB(x, y);
+ int blue = pixel & 0xff;
+ binary.append(blue & 1);
+
+ if (binary.length() == 8) {
+ int ascii = Integer.parseInt(binary.toString(), 2);
+ char character = (char) ascii;
+ binary.setLength(0);
+
+ if (!foundDelimiter) {
+ if (character == ':') {
+ foundDelimiter = true;
+ count = Integer.parseInt(lengthStr.toString());
+ } else {
+ lengthStr.append(character);
+ }
+ } else {
+ message.append(character);
+ if (message.length() == count) {
+ break outer;
+ }
+ }
+ }
+ }
+ }
+
+ return message.toString();
+ }
+
+ public BufferedImage getImage() {
+ return image;
+ }
+
+ public void setImage(BufferedImage image) {
+ this.image = image;
+ }
+}
\ No newline at end of file
diff --git a/src/Classes/Steganography/Steganography.java b/src/Classes/Steganography/Steganography.java
new file mode 100644
index 0000000..69b89ba
--- /dev/null
+++ b/src/Classes/Steganography/Steganography.java
@@ -0,0 +1,25 @@
+package Classes.Steganography;
+
+import java.io.IOException;
+
+public class Steganography {
+ protected String content;
+
+ public void encode(String message) throws IOException {
+ }
+
+ public String decode() throws IOException {
+ return null;
+ }
+
+ public String getContent() {
+ return this.content;
+ }
+
+ public void setContent(String content) {
+ if (content == null) {
+ throw new IllegalArgumentException("Content cannot be null");
+ }
+ this.content = content;
+ }
+}
\ No newline at end of file
diff --git a/src/Classes/Steganography/Text.java b/src/Classes/Steganography/Text.java
new file mode 100644
index 0000000..670f874
--- /dev/null
+++ b/src/Classes/Steganography/Text.java
@@ -0,0 +1,100 @@
+package Classes.Steganography;
+
+public class Text extends Steganography {
+ private String stegoText;
+ private String content;
+
+ @Override
+ public void encode(String message) {
+ validateMessage(message);
+ validateContent();
+
+ String binary = convertToBinary(message);
+ this.stegoText = embedMessage(binary);
+ }
+
+ private void validateMessage(String message) {
+ if (message == null || message.isEmpty()) {
+ throw new IllegalArgumentException("Message cannot be empty");
+ }
+ }
+
+ private void validateContent() {
+ if (content == null || content.trim().isEmpty()) {
+ throw new IllegalStateException("Content cannot be empty");
+ }
+ }
+
+ private String convertToBinary(String message) {
+ StringBuilder binary = new StringBuilder();
+ for (char c : message.toCharArray()) {
+ String binaryChar = String.format("%8s", Integer.toBinaryString(c))
+ .replace(' ', '0');
+ binary.append(binaryChar);
+ }
+ return binary.toString();
+ }
+
+ private String embedMessage(String binary) {
+ String[] words = content.split("\\s+");
+ int requiredSpaces = binary.length();
+
+ if (words.length - 1 < requiredSpaces) {
+ throw new IllegalStateException(
+ "Content is too short to encode the message. Need at least " +
+ (requiredSpaces + 1) + " words, but got " + words.length);
+ }
+
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < words.length; i++) {
+ result.append(words[i]);
+
+ if (i < binary.length()) {
+ // Add either two spaces (for 1) or one space (for 0)
+ result.append(binary.charAt(i) == '1' ? " " : " ");
+ } else if (i < words.length - 1) {
+ // Add normal space for remaining words
+ result.append(" ");
+ }
+ }
+ return result.toString();
+ }
+
+ @Override
+ public String decode() {
+ if (stegoText == null) {
+ throw new IllegalStateException("No encoded message found");
+ }
+
+ StringBuilder binary = new StringBuilder();
+ String[] parts = stegoText.split("\\S+");
+
+ // Skip first empty part if exists
+ for (int i = 1; i < parts.length; i++) {
+ if (!parts[i].isEmpty()) {
+ binary.append(parts[i].length() > 1 ? "1" : "0");
+ }
+ }
+
+ // Convert binary back to text
+ StringBuilder message = new StringBuilder();
+ String binaryStr = binary.toString();
+
+ for (int i = 0; i + 7 < binaryStr.length(); i += 8) {
+ String byteStr = binaryStr.substring(i, i + 8);
+ int charCode = Integer.parseInt(byteStr, 2);
+ message.append((char) charCode);
+ }
+
+ return message.toString().trim(); // Add trim() here
+ }
+
+ @Override
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+}
\ No newline at end of file
diff --git a/src/Classes/Steganography/Video.java b/src/Classes/Steganography/Video.java
new file mode 100644
index 0000000..b0fd249
--- /dev/null
+++ b/src/Classes/Steganography/Video.java
@@ -0,0 +1,247 @@
+package Classes.Steganography;
+
+import org.bytedeco.ffmpeg.global.avcodec;
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+import org.bytedeco.javacv.FFmpegFrameRecorder;
+import org.bytedeco.javacv.Frame;
+import org.bytedeco.javacv.Java2DFrameConverter;
+import org.bytedeco.ffmpeg.global.avutil;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * The {@code Video} class provides methods to encode and decode messages within video files using steganography.
+ *
+ * WARNING: This implementation is currently not functional.
+ *
+ * This class uses FFmpeg for video processing and Java2D for image manipulation. The message is encoded into the
+ * video frames by modifying the least significant bit of the pixel values.
+ *
+ * Usage:
+ *
+ * {@code
+ * File inputFile = new File("path/to/input/video.mp4");
+ * File outputFile = new File("path/to/output/video.mp4");
+ * Video videoSteganography = new Video(inputFile, outputFile);
+ *
+ * // Encode a message
+ * videoSteganography.encode("Your secret message");
+ *
+ * // Decode the message
+ * String decodedMessage = videoSteganography.decode();
+ * }
+ *
+ *
+ * Note: Ensure that the input and output files are valid and accessible.
+ *
+ * @see Steganography
+ */
+public class Video extends Steganography {
+ private File inputFile;
+ private File outputFile;
+ private static final String END_MARKER = "###END###";
+ private static final int PIXELS_PER_FRAME = 1000;
+
+ static {
+ avutil.av_log_set_level(avutil.AV_LOG_QUIET); // Suppress FFmpeg logs
+ }
+
+ // WARNING: This implementation is currently not functional.
+ public Video(File inputFile, File outputFile) throws IOException {
+ if (!inputFile.exists()) {
+ throw new IOException("Input file does not exist: " + inputFile.getAbsolutePath());
+ }
+ this.inputFile = inputFile;
+ this.outputFile = outputFile;
+
+ File outputDir = outputFile.getParentFile();
+ if (outputDir != null && !outputDir.exists()) {
+ if (!outputDir.mkdirs()) {
+ throw new IOException("Failed to create output directory: " + outputDir.getAbsolutePath());
+ }
+ }
+ }
+
+ @Override
+ public void encode(String message) throws IOException {
+ if (message == null || message.isEmpty()) {
+ throw new IllegalArgumentException("Message cannot be null or empty");
+ }
+
+ message = message + END_MARKER; // Append end marker to the message
+ byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
+ System.out.println("[DEBUG] Encoding message: '" + message + "'");
+ System.out.println("[DEBUG] Message bytes length: " + messageBytes.length);
+
+ try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
+ Java2DFrameConverter converter = new Java2DFrameConverter()) {
+
+ grabber.start();
+ FFmpegFrameRecorder recorder = createRecorder(grabber);
+
+ try {
+ recorder.start();
+ int totalBits = messageBytes.length * 8; // Total bits to encode
+ int encodedBits = 0;
+ Frame frame;
+ int frameCount = 0;
+ boolean messageDone = false;
+
+ while ((frame = grabber.grab()) != null) {
+ if (frame.image != null) {
+ BufferedImage img = converter.convert(frame);
+
+ if (!messageDone && encodedBits < totalBits) {
+ for (int i = 0; i < PIXELS_PER_FRAME && encodedBits < totalBits; i++) {
+ int x = (i % (img.getWidth() - 1)) + 1;
+ int y = (i / (img.getWidth() - 1)) + 1;
+
+ int byteIndex = encodedBits / 8;
+ int bitIndex = 7 - (encodedBits % 8);
+ int bit = (messageBytes[byteIndex] >> bitIndex) & 1;
+
+ embedBitInPixel(img, x, y, 0, bit); // Embed bit in pixel
+ encodedBits++;
+ }
+
+ if (encodedBits >= totalBits) {
+ messageDone = true;
+ }
+ }
+
+ frame = converter.convert(img);
+ recorder.record(frame);
+ frameCount++;
+
+ if (frameCount % 30 == 0) {
+ System.out.println("[DEBUG] Processed frames: " + frameCount + ", Encoded bits: " + encodedBits + "/" + totalBits);
+ }
+ }
+ }
+
+ System.out.println("[DEBUG] Total frames processed: " + frameCount);
+ System.out.println("[DEBUG] Total bits encoded: " + encodedBits);
+
+ recorder.stop();
+ recorder.release();
+
+ } catch (Exception e) {
+ cleanupOnError(recorder);
+ throw e;
+ }
+ }
+ }
+
+ private FFmpegFrameRecorder createRecorder(FFmpegFrameGrabber grabber) {
+ FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
+ outputFile,
+ grabber.getImageWidth(),
+ grabber.getImageHeight()
+ );
+ recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
+ recorder.setFormat("mp4");
+ recorder.setFrameRate(grabber.getFrameRate());
+ recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
+ recorder.setVideoQuality(0);
+ recorder.setVideoOption("preset", "veryslow");
+ recorder.setVideoOption("crf", "18");
+ return recorder;
+ }
+
+ @Override
+ public String decode() throws IOException {
+ StringBuilder binaryMessage = new StringBuilder();
+ byte[] messageBytes = new byte[1024 * 1024];
+ int messageLength = 0;
+ int bitsRead = 0;
+
+ try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(outputFile);
+ Java2DFrameConverter converter = new Java2DFrameConverter()) {
+
+ grabber.start();
+ System.out.println("[DEBUG] Starting decoding process");
+
+ Frame frame;
+ int frameCount = 0;
+ byte currentByte = 0;
+ int bitCount = 0;
+ while ((frame = grabber.grab()) != null) {
+ if (frame.image != null) {
+ BufferedImage img = converter.convert(frame);
+
+ for (int i = 0; i < PIXELS_PER_FRAME; i++) {
+ int x = (i % (img.getWidth() - 1)) + 1;
+ int y = (i / (img.getWidth() - 1)) + 1;
+
+ int bit = extractBitFromPixel(img, x, y, 0); // Extract bit from pixel
+ currentByte = (byte) ((currentByte << 1) | bit);
+ bitCount++;
+ bitsRead++;
+
+ if (bitCount == 8) {
+ messageBytes[messageLength++] = currentByte;
+ currentByte = 0;
+ bitCount = 0;
+
+ String currentMessage = new String(messageBytes, 0, messageLength, StandardCharsets.UTF_8);
+ if (currentMessage.contains(END_MARKER)) {
+ String result = currentMessage.substring(0, currentMessage.indexOf(END_MARKER));
+ System.out.println("[DEBUG] Found end marker at length: " + messageLength);
+ return result;
+ }
+ }
+ }
+
+ frameCount++;
+ if (frameCount % 30 == 0) {
+ System.out.println("[DEBUG] Processed frames: " + frameCount + ", Bits read: " + bitsRead);
+ }
+ }
+ }
+
+ System.out.println("[DEBUG] Total frames processed: " + frameCount);
+ System.out.println("[DEBUG] Total bits read: " + bitsRead);
+ System.out.println("[DEBUG] Message length: " + messageLength);
+
+ throw new IOException("Failed to decode message: End marker not found or message corrupted");
+ }
+ }
+
+ private void embedBitInPixel(BufferedImage img, int x, int y, int channel, int bit) {
+ int rgb = img.getRGB(x, y);
+ int[] channels = {
+ (rgb >> 16) & 0xFF,
+ (rgb >> 8) & 0xFF,
+ rgb & 0xFF
+ };
+
+ channels[channel] = (channels[channel] & ~1) | bit; // Embed bit in the specified channel
+
+ rgb = (channels[0] << 16) | (channels[1] << 8) | channels[2];
+ img.setRGB(x, y, rgb);
+ }
+
+ private int extractBitFromPixel(BufferedImage img, int x, int y, int channel) {
+ int rgb = img.getRGB(x, y);
+ int[] channels = {
+ (rgb >> 16) & 0xFF,
+ (rgb >> 8) & 0xFF,
+ rgb & 0xFF
+ };
+ return channels[channel] & 1; // Extract bit from the specified channel
+ }
+
+ private void cleanupOnError(FFmpegFrameRecorder recorder) {
+ try {
+ recorder.stop();
+ recorder.release();
+ } catch (Exception ex) {
+ }
+ if (outputFile.exists()) {
+ outputFile.delete(); // Delete output file on error
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Classes/VigenereAlgo.java b/src/Classes/VigenereAlgo.java
new file mode 100644
index 0000000..673ba81
--- /dev/null
+++ b/src/Classes/VigenereAlgo.java
@@ -0,0 +1,146 @@
+package Classes;
+
+
+public class VigenereAlgo {
+
+
+ String plainText = "TEST";
+
+ String key = "LONGKEY";
+ // Call encryption function and display the result
+ String encryptedText = encrypt(plainText, key);
+
+
+ // Call decryption function and display the result
+ String decryptedText = decrypt(encryptedText, key);
+
+
+ // Validate that the key does not contain numbers
+ private static boolean isValidKey(String key) {
+ for (char c : key.toCharArray()) {
+ if (Character.isDigit(c)) {
+ return false; // Reject if the key contains any digit
+ }
+ }
+ return true; // Key is valid if it contains no digits
+ }
+
+ // Encrypt the plaintext using the Vigenere cipher algorithm
+ public static String encrypt(String plainText, String key) {
+ if (!isValidKey(key)) {
+ throw new IllegalArgumentException("Key must contain only alphabetic characters.");
+ }
+
+ StringBuilder encryptedText = new StringBuilder();
+
+ // Clean the key to contain only alphabetical characters
+ key = cleanKey(key);
+ // Generate a full-length key that matches the length of the plaintext
+ key = generateFullKey(plainText, key);
+
+ for (int i = 0, keyIndex = 0; i < plainText.length(); i++) {
+ char pi = plainText.charAt(i);
+
+ // Only encrypt alphabetic characters
+ if (Character.isLetter(pi)) {
+ boolean isUpperCase = Character.isUpperCase(pi);
+ char normalizedPi = Character.toLowerCase(pi); // the calculations are based on lowerCase alphabet
+ char ki = key.charAt(keyIndex++);
+
+
+ // encrypt formula
+ // normalizedPi - a : converts the character to an index between 0 and 25 (ex : normalizedPi = 'c' (ASCII 99), then 'c' - 'a' = 99-97 = 2)
+ // ki - 'a' similarly normalizes the key character to the same 0–25 range.
+
+ // normalizedPi - 'a' and ki - 'a' are added together to combine the plaintext and key in the normalized alphabet range.
+
+ // % 26 ensures the result wraps around if it exceeds 25 (e.g., for 'z').
+ // Example: If normalizedPi = 'z' (25) and ki = 'y' (24), then:
+ // (25 + 24) % 26 = 49 % 26 = 23 (which corresponds to 'x').
+
+
+ // + 'a' converts the normalized result (0–25) back into a valid ASCII character (alphabetical range).
+ // Example: If the result is 2, adding 'a' (97) gives 99, which corresponds to 'c' in ASCII.
+ // (char) : Casts the result back to a character
+ char ci = (char) (((normalizedPi - 'a' + ki - 'a') % 26) + 'a');
+ // + 'a' converts the normalized result (0 - 25) back into a valid ASCII character (97-122)
+ encryptedText.append(isUpperCase ? Character.toUpperCase(ci) : ci);
+ } else {
+ // Keep non-alphabetic characters unchanged
+ encryptedText.append(pi);
+ }
+ }
+
+ return encryptedText.toString();
+ }
+
+ // Decrypt the ciphertext using the Vigenere cipher algorithm
+ public static String decrypt(String encryptedText, String key) {
+ if (!isValidKey(key)) {
+ throw new IllegalArgumentException("Key must contain only alphabetic characters.");
+ }
+
+ StringBuilder decryptedText = new StringBuilder();
+
+ // Clean the key to contain only alphabetical characters
+ key = cleanKey(key);
+ // Generate a full-length key that matches the length of the ciphertext
+ key = generateFullKey(encryptedText, key);
+
+ for (int i = 0, keyIndex = 0; i < encryptedText.length(); i++) {
+ char ci = encryptedText.charAt(i);
+
+ // Only decrypt alphabetic characters
+ if (Character.isLetter(ci)) {
+ boolean isUpperCase = Character.isUpperCase(ci);
+ char normalizedCi = Character.toLowerCase(ci);
+ char ki = key.charAt(keyIndex++);
+
+ // Decryption formula: Pi = (Ci - Ki + 26) mod 26
+ char pi = (char) (((normalizedCi - ki + 26) % 26) + 'a');
+ decryptedText.append(isUpperCase ? Character.toUpperCase(pi) : pi);
+ } else {
+ // Keep non-alphabetic characters unchanged
+ decryptedText.append(ci);
+ }
+ }
+
+ return decryptedText.toString();
+ }
+
+
+ // Generate a full-length key matching the text length, ignoring non-alphabetic characters
+ public static String generateFullKey(String text, String key) {
+ StringBuilder fullKey = new StringBuilder();
+ int keyLength = key.length();
+ int keyIndex = 0;
+
+ // go threw the text length
+ for (int i = 0; i < text.length(); i++) {
+ char currentChar = text.charAt(i);
+ if (Character.isLetter(currentChar)) {
+ // if keyLength > KeyIndex : troncate the keyLength to keyIndex
+ fullKey.append(key.charAt(keyIndex % keyLength));
+ keyIndex++;
+ }
+ }
+
+ return fullKey.toString();
+ }
+
+
+
+
+ // Remove non-alphabetical characters from the key
+ private static String cleanKey(String key) {
+ StringBuilder cleanedKey = new StringBuilder();
+
+ for (char c : key.toCharArray()) {
+ if (Character.isLetter(c)) {
+ cleanedKey.append(Character.toLowerCase(c));
+ }
+ }
+
+ return cleanedKey.toString();
+ }
+}
diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c45f744
--- /dev/null
+++ b/src/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Main-Class: Classes.Menu
+Class-Path: src
+
diff --git a/src/Main.java b/src/Main.java
index d5238c9..265783a 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -1,5 +1,7 @@
+import Classes.Menu;
+
public class Main {
public static void main(String[] args) {
- System.out.println("Hello, World!");
+ Menu.main(null);
}
}
\ No newline at end of file
diff --git a/src/Tests/DatabasesManagerTest.java b/src/Tests/DatabasesManagerTest.java
new file mode 100644
index 0000000..e69de29
diff --git a/src/Tests/EnigmaTest.java b/src/Tests/EnigmaTest.java
new file mode 100644
index 0000000..8066df6
--- /dev/null
+++ b/src/Tests/EnigmaTest.java
@@ -0,0 +1,155 @@
+package Tests;
+
+import Classes.Enigma.Enigma;
+import Classes.Enigma.Plugboard;
+import Classes.Enigma.Reflector;
+import Classes.Enigma.Rotors;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class EnigmaTest {
+
+ @Test
+ public void testPlugboardConnection() {
+ Plugboard plugboard = new Plugboard();
+ // Test basic connection
+ plugboard.connect('A', 'B');
+ assertEquals('B', plugboard.swap('A'));
+ assertEquals('A', plugboard.swap('B'));
+ assertEquals('C', plugboard.swap('C')); // Unconnected letter should return itself
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testPlugboardDoubleConnection() {
+ Plugboard plugboard = new Plugboard();
+ plugboard.connect('A', 'B');
+ plugboard.connect('A', 'C'); // Should throw exception
+ }
+
+ @Test
+ public void testRotorStepping() {
+ Rotors rotors = new Rotors();
+ char[] initialPositions = {'A', 'A', 'A'};
+ rotors.setPositions(initialPositions);
+
+ // Test basic rotation
+ char result = rotors.rotate('A');
+ assertNotEquals('A', result);
+
+ // Test multiple characters to ensure proper stepping
+ String input = "HELLO";
+ StringBuilder output = new StringBuilder();
+ for (char c : input.toCharArray()) {
+ output.append(rotors.rotate(c));
+ }
+ assertNotEquals(input, output.toString());
+ }
+
+ @Test
+ public void testCompleteEnigmaEncryption() {
+ // Create Enigma machine components
+ Rotors rotors = new Rotors();
+ Reflector reflector = new Reflector();
+ Plugboard plugboard = new Plugboard();
+
+ // Set up plugboard connections
+ plugboard.connect('A', 'M');
+ plugboard.connect('B', 'N');
+ plugboard.connect('C', 'O');
+
+ // Create Enigma machine
+ Enigma enigma = new Enigma(rotors, reflector, plugboard);
+
+ // Test encryption
+ String message = "HELLO WORLD";
+ String encrypted = enigma.encrypt(message);
+
+ // Test that encryption changes the message
+ assertNotEquals(message, encrypted);
+
+ // Test that decryption returns the original message
+ String decrypted = enigma.decrypt(encrypted);
+ assertEquals(message, decrypted);
+ }
+
+ @Test
+ public void testRotorPosition() {
+ Rotors rotors = new Rotors();
+ char[] positions = {'B', 'C', 'D'};
+ rotors.setPositions(positions);
+
+ // Encrypt same letter multiple times to test different rotor positions
+ String input = "AAAAA";
+ StringBuilder output = new StringBuilder();
+ for (char c : input.toCharArray()) {
+ output.append(rotors.rotate(c));
+ }
+
+ // Each 'A' should encrypt to a different letter due to rotor movement
+ String result = output.toString();
+ for (int i = 1; i < result.length(); i++) {
+ assertNotEquals(result.charAt(i-1), result.charAt(i));
+ }
+ }
+
+ @Test
+ public void testReflector() {
+ Reflector reflector = new Reflector();
+ char input = 'A';
+ char reflected = reflector.reflect(input);
+
+ // Test that reflection is consistent
+ assertEquals(reflected, reflector.reflect(input));
+
+ // Test that reflection is reciprocal
+ assertEquals(input, reflector.reflect(reflected));
+ }
+
+ @Test
+ public void testLongMessage() {
+ Enigma enigma = new Enigma();
+ // Set initial rotor positions
+ char[] initialPositions = {'A', 'A', 'A'};
+ enigma.getRotors().setPositions(initialPositions);
+
+ String longMessage = "THIS IS A VERY LONG MESSAGE THAT SHOULD TEST THE FULL FUNCTIONALITY " +
+ "OF THE ENIGMA MACHINE INCLUDING MULTIPLE ROTOR ROTATIONS AND STEPPING";
+
+ String encrypted = enigma.encrypt(longMessage);
+ String decrypted = enigma.decrypt(encrypted);
+
+ // Test that encryption changes the message
+ assertNotEquals(longMessage, encrypted);
+
+ // Test that decryption recovers the original message
+ assertEquals(longMessage, decrypted);
+ }
+
+ @Test
+ public void testNonAlphabeticCharacters() {
+ Enigma enigma = new Enigma();
+ String message = "HELLO, WORLD! 123";
+ String encrypted = enigma.encrypt(message);
+ String decrypted = enigma.decrypt(encrypted);
+
+ // Test that non-alphabetic characters remain unchanged
+ assertTrue(encrypted.contains(","));
+ assertTrue(encrypted.contains("!"));
+ assertTrue(encrypted.contains("123"));
+
+ // Test that the original message is recovered
+ assertEquals(message, decrypted);
+ }
+
+ @Test
+ public void testCaseSensitivity() {
+ Enigma enigma = new Enigma();
+ String message = "Hello World";
+ String encrypted = enigma.encrypt(message);
+ String decrypted = enigma.decrypt(encrypted);
+
+ // Test that the case of the original message is preserved
+ assertEquals(message, decrypted);
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/HashTest.java b/src/Tests/HashTest.java
new file mode 100644
index 0000000..5c7af4d
--- /dev/null
+++ b/src/Tests/HashTest.java
@@ -0,0 +1,29 @@
+package Tests;
+
+import Classes.Hash;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class HashTest {
+
+ private class DummyHash extends Hash {
+ @Override
+ public String calculateHash(String input) {
+ return "dummyhash";
+ }
+ }
+
+ @Test
+ public void testPrintHash() {
+ DummyHash dummyHash = new DummyHash();
+ dummyHash.printHash("test");
+ }
+
+ @Test
+ public void testCalculateHash() {
+ DummyHash dummyHash = new DummyHash();
+ String result = dummyHash.calculateHash("test");
+ assertEquals("dummyhash", result);
+ }
+}
+
diff --git a/src/Tests/LfsrTest.java b/src/Tests/LfsrTest.java
new file mode 100644
index 0000000..86a58a8
--- /dev/null
+++ b/src/Tests/LfsrTest.java
@@ -0,0 +1,102 @@
+package Tests;
+
+import Classes.Lfsr;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class LfsrTest {
+ private Lfsr lfsr;
+
+ @Before
+ public void setUp() {
+ lfsr = new Lfsr((char) 0, (char) 0);
+ }
+
+ @Test
+ public void testParity() {
+ // Test the parity (XOR of all bits)
+ assertEquals(0, Lfsr.parity(0)); // 0000 -> parity 0
+ assertEquals(1, Lfsr.parity(1)); // 0001 -> parity 1
+ assertEquals(0, Lfsr.parity(3)); // 0011 -> parity 0 (1 XOR 1 = 0)
+ assertEquals(1, Lfsr.parity(7)); // 0111 -> parity 1 (1 XOR 1 XOR 1 = 1)
+ assertEquals(0, Lfsr.parity(15)); // 1111 -> parity 0 (1 XOR 1 XOR 1 XOR 1 = 0)
+ }
+
+ @Test
+ public void testConvertor() {
+ assertEquals("0000000000000000", Lfsr.convertor(0));
+ assertEquals("0000000000000001", Lfsr.convertor(1));
+ assertEquals("0000000000001111", Lfsr.convertor(15));
+ }
+
+ @Test
+ public void testFibonacciBasic() {
+ lfsr = new Lfsr((char) 1, (char) 1); // Simple initial state
+ String result = lfsr.fibonacci(4);
+ assertNotNull(result);
+ assertEquals(4, result.length());
+ }
+
+ @Test
+ public void testGaloisBasic() {
+ lfsr = new Lfsr((char) 1, (char) 1); // Simple initial state
+ String result = lfsr.galois(4);
+ assertNotNull(result);
+ assertEquals(4, result.length());
+ }
+
+ @Test
+ public void testLfsrBasicOperation() {
+ // Test with simple values
+ String result = lfsr.lfsr("1", 4, "1", "galois");
+ assertNotNull(result);
+ assertEquals(4, result.length());
+ }
+
+ @Test
+ public void testDifferentModes() {
+ String galoisResult = lfsr.lfsr("1", 4, "1", "galois");
+ String fibonacciResult = lfsr.lfsr("1", 4, "1", "fibonacci");
+ // The results should be different for the two modes
+ assertNotEquals(galoisResult, fibonacciResult);
+ }
+
+ @Test
+ public void testOutputLength() {
+ String result4 = lfsr.lfsr("1", 4, "1", "galois");
+ String result8 = lfsr.lfsr("1", 8, "1", "galois");
+ assertEquals(4, result4.length());
+ assertEquals(8, result8.length());
+ }
+
+ @Test
+ public void testConsistency() {
+ // The same input should give the same output
+ String result1 = lfsr.lfsr("1", 4, "1", "galois");
+ String result2 = lfsr.lfsr("1", 4, "1", "galois");
+ assertEquals(result1, result2);
+ }
+
+ @Test
+ public void testModeInsensitiveCase() {
+ String result1 = lfsr.lfsr("1", 4, "1", "GALOIS");
+ String result2 = lfsr.lfsr("1", 4, "1", "galois");
+ assertEquals(result1, result2);
+ }
+
+ @Test
+ public void testWithZeroTaps() {
+ String result = lfsr.lfsr("0", 4, "1", "galois");
+ assertNotNull(result);
+ assertEquals(4, result.length());
+ }
+
+ @Test
+ public void testWithZeroSeed() {
+ String result = lfsr.lfsr("1", 4, "0", "galois");
+ assertNotNull(result);
+ assertEquals(4, result.length());
+ assertEquals("0000", result); // With seed 0, the output should be all 0s
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/MD5Test.java b/src/Tests/MD5Test.java
new file mode 100644
index 0000000..d5397ff
--- /dev/null
+++ b/src/Tests/MD5Test.java
@@ -0,0 +1,82 @@
+package Tests;
+
+import Classes.MD5;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Assert;
+
+public class MD5Test {
+
+ private MD5 md5;
+
+ @Before
+ public void setUp() {
+ md5 = new MD5();
+ }
+ @Test
+ public void testEmptyString() {
+
+ String result = md5.calculateHash("");
+ Assert.assertEquals("d41d8cd98f00b204e9800998ecf8427e", result);
+ }
+
+ @Test
+ public void testSimpleString() {
+ String result = md5.calculateHash("test");
+ Assert.assertEquals("098f6bcd4621d373cade4e832627b4f6", result);
+ }
+
+ @Test
+ public void testLongString() {
+ String result = md5.calculateHash("The quick brown fox jumps over the lazy dog");
+ Assert.assertEquals("9e107d9d372bb6826bd81d3542a419d6", result);
+ }
+
+ @Test
+ public void testSpecialCharacters() {
+ String result = md5.calculateHash("!@#$%^&*()_+");
+ Assert.assertEquals("04dde9f462255fe14b5160bbf2acffe8", result);
+ }
+
+ @Test
+ public void testUnicodeCharacters() {
+ String result = md5.calculateHash("héllo wörld");
+ Assert.assertEquals("ed0c22cc110ede12327851863c078138", result);
+ }
+
+ @Test
+ public void testConsistency() {
+ String input = "test123";
+ String firstHash = md5.calculateHash(input);
+ String secondHash = md5.calculateHash(input);
+ Assert.assertEquals("The same input should produce the same hash", firstHash, secondHash);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testNullInput() {
+ md5.calculateHash(null);
+ }
+
+ @Test
+ public void testCaseSensitivity() {
+ String lowerCase = md5.calculateHash("hello");
+ String upperCase = md5.calculateHash("HELLO");
+ Assert.assertNotEquals("Hashes of different cases should be different",
+ lowerCase, upperCase);
+ }
+
+ @Test
+ public void testHashLength() {
+ String result = md5.calculateHash("test");
+ Assert.assertEquals("The length of the md5 hash should be 32 characters",
+ 32, result.length());
+ }
+
+ @Test
+ public void testWhitespaceHandling() {
+ String withSpaces = md5.calculateHash("test test");
+ String withoutSpaces = md5.calculateHash("testtest");
+ Assert.assertNotEquals("Spaces should affect the hash",
+ withSpaces, withoutSpaces);
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/PasswordUtilsTest.java b/src/Tests/PasswordUtilsTest.java
new file mode 100644
index 0000000..0d59604
--- /dev/null
+++ b/src/Tests/PasswordUtilsTest.java
@@ -0,0 +1,20 @@
+package Tests;
+
+import Classes.PasswordUtils;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class PasswordUtilsTest {
+
+ @Test
+ public void testGenerateRandomPassword() {
+ String password1 = PasswordUtils.generateRandomPassword(12);
+ String password2 = PasswordUtils.generateRandomPassword(12);
+
+ assertNotEquals(password1, password2);
+
+ assertEquals(12, password1.length());
+ assertEquals(12, password2.length());
+ }
+}
diff --git a/src/Tests/PolybSquareEncryterTest.java b/src/Tests/PolybSquareEncryterTest.java
new file mode 100644
index 0000000..084c2e3
--- /dev/null
+++ b/src/Tests/PolybSquareEncryterTest.java
@@ -0,0 +1,86 @@
+package Tests;
+
+import Classes.PolybSquareEncrypter;
+import Classes.PolybSquareLayout;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class PolybSquareEncryterTest
+{
+ private PolybSquareEncrypter horizontalLayoutPolybSquareEncrypter;
+
+ // Horizontal layout
+
+ // Encryption
+ @Before
+ public void setUp() {
+ this.horizontalLayoutPolybSquareEncrypter = new PolybSquareEncrypter(PolybSquareLayout.HORIZONTAL);
+ }
+
+ @Test
+ public void testPolybSquareEncryterEncryption() {
+ String plainText = ("hello");
+ String expectedEncryptedText = "3251232353";
+ String encryptionResult = this.horizontalLayoutPolybSquareEncrypter.encrypt(plainText);
+
+ // Validation
+ assertEquals(expectedEncryptedText, encryptionResult);
+ }
+
+ @Test
+ public void testPolybSquareEncryterEncryptionEmptyString() {
+ String plainText = ("");
+ String expectedEncryptedText = "";
+ String encryptionResult = this.horizontalLayoutPolybSquareEncrypter.encrypt(plainText);
+
+ // Validation
+ assertEquals(expectedEncryptedText, encryptionResult);
+ }
+
+ @Test
+ public void testPolybSquareEncryterEncryptionW() {
+ String plainText = ("w");
+ String expectedEncryptedText = "2525";
+ String encryptionResult = this.horizontalLayoutPolybSquareEncrypter.encrypt(plainText);
+
+ // Validation
+ assertEquals(expectedEncryptedText, encryptionResult);
+ }
+
+ // Decryption
+ @Test
+ public void testPolybSquareEncryterDecryption() {
+ String encryptedText = ("3251232353");
+ String expectedPlainText = "hello";
+ String decryptionResult = this.horizontalLayoutPolybSquareEncrypter.decrypt(encryptedText);
+
+ // Validation
+ assertEquals(expectedPlainText, decryptionResult);
+ }
+
+ @Test
+ public void testPolybSquareEncryterDecryptionEmptyString() {
+ String encryptedText = ("");
+ String expectedPlainText = "";
+ String decryptionResult = this.horizontalLayoutPolybSquareEncrypter.decrypt(encryptedText);
+
+ // Validation
+ assertEquals(expectedPlainText, decryptionResult);
+ }
+
+ @Test
+ public void testPolybSquareEncryterDecryptionW() {
+ String encryptedText = ("2525");
+ String expectedPlainText = "vv";
+ String decryptionResult = this.horizontalLayoutPolybSquareEncrypter.decrypt(encryptedText);
+
+ // Validation
+ assertEquals(expectedPlainText, decryptionResult);
+ }
+
+ // TODO Vertical Layout
+ // TODO ClockWise spiral layout
+ // TODO CounterClockWise spiral layout
+}
diff --git a/src/Tests/RC4Test.java b/src/Tests/RC4Test.java
new file mode 100644
index 0000000..558e41f
--- /dev/null
+++ b/src/Tests/RC4Test.java
@@ -0,0 +1,128 @@
+package Tests;
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.Assert;
+import Classes.RC4;
+
+public class RC4Test {
+ private RC4 rc4;
+ private static final String KEY = "1234";
+ private static final String CLEAR_TEXT = "Hello World";
+ private static final String ENCRYPTED_TEXT = "01001101 00101100 00011101 11000011 10011100 11001100 01010000 01100010 01111101 01110111 01100100";
+
+ @Before
+ public void setUp() {
+ rc4 = new RC4();
+ rc4.key = KEY;
+ rc4.init(KEY);
+ }
+
+ @Test
+ public void testInit() {
+ RC4 testRc4 = new RC4();
+ testRc4.init(KEY);
+ Assert.assertNotNull("Initialization should not produce a null array", testRc4);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInitWithNullKey() {
+ rc4.init(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInitWithEmptyKey() {
+ rc4.init("");
+ }
+
+ @Test
+ public void testEncrypt() {
+ String encrypted = rc4.encrypt(CLEAR_TEXT);
+ Assert.assertEquals("The encrypted text does not match the expected result",
+ ENCRYPTED_TEXT, encrypted);
+ }
+
+ @Test
+ public void testEncryptEmptyString() {
+ try {
+ rc4.encrypt("");
+ Assert.fail("An empty string should throw an exception");
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testEncryptNull() {
+ rc4.encrypt(null);
+ }
+
+ @Test
+ public void testDecrypt() {
+ String decrypted = rc4.decrypt(ENCRYPTED_TEXT);
+ Assert.assertEquals("The decrypted text does not match the original text",
+ CLEAR_TEXT, decrypted);
+ }
+
+ @Test
+ public void testDecryptEmptyString() {
+ try {
+ rc4.decrypt("");
+ Assert.fail("An empty string should throw an exception");
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDecryptNull() {
+ rc4.decrypt(null);
+ }
+
+ @Test
+ public void testFullCycle() {
+ String encrypted = rc4.encrypt(CLEAR_TEXT);
+ rc4.init(KEY); // Reinitialization needed for decryption
+ String decrypted = rc4.decrypt(encrypted);
+ Assert.assertEquals("The full encryption/decryption cycle failed",
+ CLEAR_TEXT, decrypted);
+ }
+
+ @Test
+ public void testDifferentKeys() {
+ String encrypted1 = rc4.encrypt(CLEAR_TEXT);
+ rc4.init("5678"); // Using a different key
+ String encrypted2 = rc4.encrypt(CLEAR_TEXT);
+ Assert.assertNotEquals("Different keys should produce different encryptions",
+ encrypted1, encrypted2);
+ }
+
+ @Test
+ public void testConsistentEncryption() {
+ String encrypted1 = rc4.encrypt(CLEAR_TEXT);
+ rc4.init(KEY);
+ String encrypted2 = rc4.encrypt(CLEAR_TEXT);
+ Assert.assertEquals("The same text with the same key should produce the same encryption",
+ encrypted1, encrypted2);
+ }
+
+ @Test
+ public void testLongText() {
+ String longText = "This is a longer text that should also work properly with RC4 encryption!";
+ String encrypted = rc4.encrypt(longText);
+ rc4.init(KEY);
+ String decrypted = rc4.decrypt(encrypted);
+ Assert.assertEquals("Encryption/decryption of a long text failed",
+ longText, decrypted);
+ }
+
+ @Test
+ public void testSpecialCharacters() {
+ String specialText = "Hello! @#$%^&*()_+ World";
+ String encrypted = rc4.encrypt(specialText);
+ rc4.init(KEY);
+ String decrypted = rc4.decrypt(encrypted);
+ Assert.assertEquals("Encryption/decryption with special characters failed",
+ specialText, decrypted);
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/ROTXTest.java b/src/Tests/ROTXTest.java
new file mode 100644
index 0000000..87e1401
--- /dev/null
+++ b/src/Tests/ROTXTest.java
@@ -0,0 +1,108 @@
+package Tests;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+import Classes.ROTX;
+
+public class ROTXTest {
+
+ // Base test with classic rotation
+ @Test
+ public void testRotationPositive() {
+ String input = "abc";
+ int shift = 3;
+ String expected = "def"; // "abc" with ROT(3) becomes "def"
+ String result = ROTX.encryptROT(input, shift);
+ assertEquals("Le texte n'est pas correctement transformé", expected, result);
+ }
+
+ // Test with a null function
+ @Test
+ public void testRotationZero() {
+ String input = "abc";
+ int shift = 0;
+ String expected = "abc"; // ROT(0) don't modify the text
+ String result = ROTX.encryptROT(input, shift);
+ assertEquals("La rotation nulle n'a pas fonctionné comme prévu", expected, result);
+ }
+
+ // Test with negative rotation
+ @Test
+ public void testRotationNegative() {
+ String input = "abc";
+ int shift = -3;
+ String expected = "xyz"; // "abc" with ROT(-3) becomes "xyz"
+ String result = ROTX.encryptROT(input, shift);
+ assertEquals("La rotation négative ne donne pas le bon résultat", expected, result);
+ }
+
+ // Test with non-alphabetical characters (spaces and symbols)
+ @Test
+ public void testNonAlphabeticCharacters() {
+ String input = "abc 123!";
+ int shift = 3;
+ String expected = "def 123!"; // Non-alphabetical characters must not be affected
+ String result = ROTX.encryptROT(input, shift);
+ assertEquals("Les caractères non alphabétiques ne sont pas correctement gérés", expected, result);
+ }
+
+ // Test on an empty text
+ @Test
+ public void testEmptyString() {
+ String input = "";
+ int shift = 5;
+ String expected = ""; // La chaîne vide ne doit pas être modifiée
+ String result = ROTX.encryptROT(input, shift);
+ assertEquals("La chaîne vide n'a pas été gérée correctement", expected, result);
+ }
+
+ // Test de décryptage avec une rotation positive
+ @Test
+ public void testDecryptionPositive() {
+ String input = "def";
+ int shift = 3;
+ String expected = "abc"; // "def" avec ROT(-3) devient "abc"
+ String result = ROTX.decryptROT(input, shift);
+ assertEquals("Le texte n'a pas été correctement décrypté", expected, result);
+ }
+
+ // Test de décryptage avec une rotation négative
+ @Test
+ public void testDecryptionNegative() {
+ String input = "xyz";
+ int shift = -3;
+ String expected = "abc"; // "xyz" avec ROT(3) devient "abc"
+ String result = ROTX.decryptROT(input, shift);
+ assertEquals("Le texte n'a pas été correctement décrypté", expected, result);
+ }
+
+ // Test de décryptage avec une rotation nulle
+ @Test
+ public void testDecryptionZero() {
+ String input = "abc";
+ int shift = 0;
+ String expected = "abc"; // ROT(0) ne modifie pas le texte
+ String result = ROTX.decryptROT(input, shift);
+ assertEquals("La décryptation nulle n'a pas fonctionné comme prévu", expected, result);
+ }
+
+ // Test de décryptage avec des caractères non alphabétiques
+ @Test
+ public void testDecryptionNonAlphabeticCharacters() {
+ String input = "def 123!";
+ int shift = 3;
+ String expected = "abc 123!"; // Les caractères non alphabétiques ne doivent pas être affectés
+ String result = ROTX.decryptROT(input, shift);
+ assertEquals("Les caractères non alphabétiques ne sont pas correctement décryptés", expected, result);
+ }
+
+ // Test de décryptage avec une chaîne vide
+ @Test
+ public void testDecryptionEmptyString() {
+ String input = "";
+ int shift = 5;
+ String expected = ""; // La chaîne vide ne doit pas être modifiée
+ String result = ROTX.decryptROT(input, shift);
+ assertEquals("La chaîne vide n'a pas été décryptée correctement", expected, result);
+ }
+}
diff --git a/src/Tests/SHA256Test.java b/src/Tests/SHA256Test.java
new file mode 100644
index 0000000..2c2bdaa
--- /dev/null
+++ b/src/Tests/SHA256Test.java
@@ -0,0 +1,28 @@
+package Tests;
+
+import Classes.Sha256;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SHA256Test {
+ @Test
+ public void testCalculateHash() {
+ Sha256 sha256 = new Sha256();
+ String input = "test";
+ String expectedHash = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08";
+
+ String result = sha256.calculateHash(input);
+ assertEquals(expectedHash, result);
+ }
+
+ @Test
+ public void testEmptyInputHash() {
+ Sha256 sha256 = new Sha256();
+ String input = "";
+ String expectedHash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
+
+ String result = sha256.calculateHash(input);
+ assertEquals(expectedHash, result);
+ }
+}
diff --git a/src/Tests/SiteManagerTest.java b/src/Tests/SiteManagerTest.java
new file mode 100644
index 0000000..7401f95
--- /dev/null
+++ b/src/Tests/SiteManagerTest.java
@@ -0,0 +1,89 @@
+package Classes;
+
+import org.junit.*;
+import java.io.File;
+import java.util.*;
+
+import static org.junit.Assert.*;
+
+public class SiteManagerTest {
+
+ private File tempFile;
+ private SiteManager siteManager;
+
+ @Before
+ public void setUp() {
+ tempFile = new File("test_db.json");
+ Map encryptionMap = Map.of("RotX", "3"); // Exemple de méthode de chiffrement
+ siteManager = new SiteManager(tempFile, encryptionMap);
+ }
+
+ @After
+ public void tearDown() {
+ if (tempFile.exists()) {
+ tempFile.delete();
+ }
+ }
+
+ @Test
+ public void testAddSite() {
+ siteManager.addSite("example.com", "user123", "pass123");
+
+ List