From c77761d361090cf5d29eeb081e7e3f04d46c8790 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 6 Oct 2024 10:52:12 +0530 Subject: [PATCH 1/4] Add tests for `A5KeyStreamGenerator.java`, improve documentation --- .../ciphers/a5/A5KeyStreamGenerator.java | 69 ++++++++++++++++++- .../ciphers/a5/A5KeyStreamGeneratorTest.java | 61 ++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java diff --git a/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java b/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java index 0b17a685bc57..ee837ef4241a 100644 --- a/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java +++ b/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java @@ -2,15 +2,39 @@ import java.util.BitSet; -// TODO: raise exceptions for improper use +/** + * The A5KeyStreamGenerator class is responsible for generating key streams + * for the A5/1 encryption algorithm using a combination of Linear Feedback Shift Registers (LFSRs). + * + *

+ * This class extends the CompositeLFSR and initializes a set of LFSRs with + * a session key and a frame counter to produce a pseudo-random key stream. + *

+ * + *

+ * Note: Proper exception handling for invalid usage is to be implemented. + *

+ */ public class A5KeyStreamGenerator extends CompositeLFSR { private BitSet initialFrameCounter; private BitSet frameCounter; private BitSet sessionKey; private static final int INITIAL_CLOCKING_CYCLES = 100; - private static final int KEY_STREAM_LENGTH = 228; // 28.5 bytes so we need to pad bytes or something + private static final int KEY_STREAM_LENGTH = 228; + /** + * Initializes the A5KeyStreamGenerator with the specified session key and frame counter. + * + *

+ * This method sets up the internal state of the LFSRs using the provided + * session key and frame counter. It creates three LFSRs with specific + * configurations and initializes them. + *

+ * + * @param sessionKey a BitSet representing the session key used for key stream generation. + * @param frameCounter a BitSet representing the frame counter that influences the key stream. + */ @Override public void initialize(BitSet sessionKey, BitSet frameCounter) { this.sessionKey = sessionKey; @@ -26,10 +50,26 @@ public void initialize(BitSet sessionKey, BitSet frameCounter) { registers.forEach(lfsr -> lfsr.initialize(sessionKey, frameCounter)); } + /** + * Re-initializes the key stream generator with the original session key + * and frame counter. This method restores the generator to its initial + * state. + */ public void reInitialize() { this.initialize(sessionKey, initialFrameCounter); } + /** + * Generates the next key stream of bits. + * + *

+ * This method performs an initial set of clocking cycles and then retrieves + * a key stream of the specified length. After generation, it re-initializes + * the internal registers. + *

+ * + * @return a BitSet containing the generated key stream bits. + */ public BitSet getNextKeyStream() { for (int cycle = 1; cycle <= INITIAL_CLOCKING_CYCLES; ++cycle) { this.clock(); @@ -45,12 +85,37 @@ public BitSet getNextKeyStream() { return result; } + /** + * Re-initializes the registers for the LFSRs. + * + *

+ * This method increments the frame counter and re-initializes each LFSR + * with the current session key and frame counter. + *

+ */ private void reInitializeRegisters() { incrementFrameCounter(); registers.forEach(lfsr -> lfsr.initialize(sessionKey, frameCounter)); } + /** + * Increments the current frame counter. + * + *

+ * This method uses a utility function to increment the frame counter, + * which influences the key stream generation process. + *

+ */ private void incrementFrameCounter() { Utils.increment(frameCounter, FRAME_COUNTER_LENGTH); } + + /** + * Retrieves the current frame counter. + * + * @return a BitSet representing the current state of the frame counter. + */ + public BitSet getFrameCounter() { + return frameCounter; + } } diff --git a/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java b/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java new file mode 100644 index 000000000000..66aaf22fdde8 --- /dev/null +++ b/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java @@ -0,0 +1,61 @@ +package com.thealgorithms.ciphers.a5; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static com.thealgorithms.ciphers.a5.A5KeyStreamGenerator.FRAME_COUNTER_LENGTH; + +import java.util.BitSet; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class A5KeyStreamGeneratorTest { + + private A5KeyStreamGenerator keyStreamGenerator; + private BitSet sessionKey; + private BitSet frameCounter; + + @BeforeEach + void setUp() { + keyStreamGenerator = new A5KeyStreamGenerator(); + + // Initialize session key and frame counter for testing + sessionKey = BitSet.valueOf(new long[]{0b1010101010101010L}); // Example 16-bit key + frameCounter = BitSet.valueOf(new long[]{0b0000000000000001L}); // Example 16-bit frame counter + keyStreamGenerator.initialize(sessionKey, frameCounter); + } + + @Test + void testInitialization() { + // Verify that the internal state is set up correctly + assertNotNull(keyStreamGenerator, "KeyStreamGenerator should be initialized"); + } + + @Test + void testIncrementFrameCounter() { + // Generate key stream to increment the frame counter + keyStreamGenerator.getNextKeyStream(); + + // The frame counter should have been incremented + BitSet incrementedFrameCounter = keyStreamGenerator.getFrameCounter(); + + // Check if the incremented frame counter is expected + BitSet expectedFrameCounter = (BitSet) frameCounter.clone(); + Utils.increment(expectedFrameCounter, FRAME_COUNTER_LENGTH); + + assertEquals(expectedFrameCounter, incrementedFrameCounter, "Frame counter should be incremented after generating key stream"); + } + + @Test + void testGetNextKeyStreamProducesDifferentOutputs() { + // Generate a key stream + BitSet firstKeyStream = keyStreamGenerator.getNextKeyStream(); + + // Generate another key stream + BitSet secondKeyStream = keyStreamGenerator.getNextKeyStream(); + + // Assert that consecutive key streams are different + assertNotEquals(firstKeyStream, secondKeyStream, "Consecutive key streams should be different"); + } +} From 2179edb604b8317a3c20c208047bb488d879b766 Mon Sep 17 00:00:00 2001 From: Hardvan Date: Sun, 6 Oct 2024 05:22:31 +0000 Subject: [PATCH 2/4] Update directory --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 1bad5d3b98a3..863c36a912ca 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -617,6 +617,7 @@ * [SingleBitOperationsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java) * ciphers * a5 + * [A5KeyStreamGeneratorTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java) * [LFSRTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/a5/LFSRTest.java) * [BlowfishTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/BlowfishTest.java) * [CaesarTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/CaesarTest.java) From 774e713f96772f1ad7e1c7f842f2c521d774f9dd Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 6 Oct 2024 10:55:06 +0530 Subject: [PATCH 3/4] Fix --- .../thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java b/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java index 66aaf22fdde8..e8aa39d074f7 100644 --- a/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java +++ b/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java @@ -1,9 +1,9 @@ package com.thealgorithms.ciphers.a5; +import static com.thealgorithms.ciphers.a5.A5KeyStreamGenerator.FRAME_COUNTER_LENGTH; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static com.thealgorithms.ciphers.a5.A5KeyStreamGenerator.FRAME_COUNTER_LENGTH; import java.util.BitSet; @@ -21,8 +21,8 @@ void setUp() { keyStreamGenerator = new A5KeyStreamGenerator(); // Initialize session key and frame counter for testing - sessionKey = BitSet.valueOf(new long[]{0b1010101010101010L}); // Example 16-bit key - frameCounter = BitSet.valueOf(new long[]{0b0000000000000001L}); // Example 16-bit frame counter + sessionKey = BitSet.valueOf(new long[] {0b1010101010101010L}); // Example 16-bit key + frameCounter = BitSet.valueOf(new long[] {0b0000000000000001L}); // Example 16-bit frame counter keyStreamGenerator.initialize(sessionKey, frameCounter); } From afc4f63420c4163a7e6f3644738f25aee3db04fe Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 6 Oct 2024 10:56:34 +0530 Subject: [PATCH 4/4] Fix --- .../com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java b/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java index e8aa39d074f7..bb18d4500fc0 100644 --- a/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java +++ b/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java @@ -6,7 +6,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.BitSet; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test;