Skip to content

Commit 93cfa86

Browse files
authored
Add tests for A5KeyStreamGenerator.java, improve documentation (TheAlgorithms#5595)
1 parent cacd23a commit 93cfa86

File tree

3 files changed

+128
-2
lines changed

3 files changed

+128
-2
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@
633633
* [SingleBitOperationsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java)
634634
* ciphers
635635
* a5
636+
* [A5KeyStreamGeneratorTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java)
636637
* [LFSRTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/a5/LFSRTest.java)
637638
* [AutokeyTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/AutokeyTest.java)
638639
* [BlowfishTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/BlowfishTest.java)

src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,39 @@
22

33
import java.util.BitSet;
44

5-
// TODO: raise exceptions for improper use
5+
/**
6+
* The A5KeyStreamGenerator class is responsible for generating key streams
7+
* for the A5/1 encryption algorithm using a combination of Linear Feedback Shift Registers (LFSRs).
8+
*
9+
* <p>
10+
* This class extends the CompositeLFSR and initializes a set of LFSRs with
11+
* a session key and a frame counter to produce a pseudo-random key stream.
12+
* </p>
13+
*
14+
* <p>
15+
* Note: Proper exception handling for invalid usage is to be implemented.
16+
* </p>
17+
*/
618
public class A5KeyStreamGenerator extends CompositeLFSR {
719

820
private BitSet initialFrameCounter;
921
private BitSet frameCounter;
1022
private BitSet sessionKey;
1123
private static final int INITIAL_CLOCKING_CYCLES = 100;
12-
private static final int KEY_STREAM_LENGTH = 228; // 28.5 bytes so we need to pad bytes or something
24+
private static final int KEY_STREAM_LENGTH = 228;
1325

26+
/**
27+
* Initializes the A5KeyStreamGenerator with the specified session key and frame counter.
28+
*
29+
* <p>
30+
* This method sets up the internal state of the LFSRs using the provided
31+
* session key and frame counter. It creates three LFSRs with specific
32+
* configurations and initializes them.
33+
* </p>
34+
*
35+
* @param sessionKey a BitSet representing the session key used for key stream generation.
36+
* @param frameCounter a BitSet representing the frame counter that influences the key stream.
37+
*/
1438
@Override
1539
public void initialize(BitSet sessionKey, BitSet frameCounter) {
1640
this.sessionKey = sessionKey;
@@ -26,10 +50,26 @@ public void initialize(BitSet sessionKey, BitSet frameCounter) {
2650
registers.forEach(lfsr -> lfsr.initialize(sessionKey, frameCounter));
2751
}
2852

53+
/**
54+
* Re-initializes the key stream generator with the original session key
55+
* and frame counter. This method restores the generator to its initial
56+
* state.
57+
*/
2958
public void reInitialize() {
3059
this.initialize(sessionKey, initialFrameCounter);
3160
}
3261

62+
/**
63+
* Generates the next key stream of bits.
64+
*
65+
* <p>
66+
* This method performs an initial set of clocking cycles and then retrieves
67+
* a key stream of the specified length. After generation, it re-initializes
68+
* the internal registers.
69+
* </p>
70+
*
71+
* @return a BitSet containing the generated key stream bits.
72+
*/
3373
public BitSet getNextKeyStream() {
3474
for (int cycle = 1; cycle <= INITIAL_CLOCKING_CYCLES; ++cycle) {
3575
this.clock();
@@ -45,12 +85,37 @@ public BitSet getNextKeyStream() {
4585
return result;
4686
}
4787

88+
/**
89+
* Re-initializes the registers for the LFSRs.
90+
*
91+
* <p>
92+
* This method increments the frame counter and re-initializes each LFSR
93+
* with the current session key and frame counter.
94+
* </p>
95+
*/
4896
private void reInitializeRegisters() {
4997
incrementFrameCounter();
5098
registers.forEach(lfsr -> lfsr.initialize(sessionKey, frameCounter));
5199
}
52100

101+
/**
102+
* Increments the current frame counter.
103+
*
104+
* <p>
105+
* This method uses a utility function to increment the frame counter,
106+
* which influences the key stream generation process.
107+
* </p>
108+
*/
53109
private void incrementFrameCounter() {
54110
Utils.increment(frameCounter, FRAME_COUNTER_LENGTH);
55111
}
112+
113+
/**
114+
* Retrieves the current frame counter.
115+
*
116+
* @return a BitSet representing the current state of the frame counter.
117+
*/
118+
public BitSet getFrameCounter() {
119+
return frameCounter;
120+
}
56121
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.thealgorithms.ciphers.a5;
2+
3+
import static com.thealgorithms.ciphers.a5.A5KeyStreamGenerator.FRAME_COUNTER_LENGTH;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
6+
import static org.junit.jupiter.api.Assertions.assertNotNull;
7+
8+
import java.util.BitSet;
9+
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Test;
11+
12+
public class A5KeyStreamGeneratorTest {
13+
14+
private A5KeyStreamGenerator keyStreamGenerator;
15+
private BitSet sessionKey;
16+
private BitSet frameCounter;
17+
18+
@BeforeEach
19+
void setUp() {
20+
keyStreamGenerator = new A5KeyStreamGenerator();
21+
22+
// Initialize session key and frame counter for testing
23+
sessionKey = BitSet.valueOf(new long[] {0b1010101010101010L}); // Example 16-bit key
24+
frameCounter = BitSet.valueOf(new long[] {0b0000000000000001L}); // Example 16-bit frame counter
25+
keyStreamGenerator.initialize(sessionKey, frameCounter);
26+
}
27+
28+
@Test
29+
void testInitialization() {
30+
// Verify that the internal state is set up correctly
31+
assertNotNull(keyStreamGenerator, "KeyStreamGenerator should be initialized");
32+
}
33+
34+
@Test
35+
void testIncrementFrameCounter() {
36+
// Generate key stream to increment the frame counter
37+
keyStreamGenerator.getNextKeyStream();
38+
39+
// The frame counter should have been incremented
40+
BitSet incrementedFrameCounter = keyStreamGenerator.getFrameCounter();
41+
42+
// Check if the incremented frame counter is expected
43+
BitSet expectedFrameCounter = (BitSet) frameCounter.clone();
44+
Utils.increment(expectedFrameCounter, FRAME_COUNTER_LENGTH);
45+
46+
assertEquals(expectedFrameCounter, incrementedFrameCounter, "Frame counter should be incremented after generating key stream");
47+
}
48+
49+
@Test
50+
void testGetNextKeyStreamProducesDifferentOutputs() {
51+
// Generate a key stream
52+
BitSet firstKeyStream = keyStreamGenerator.getNextKeyStream();
53+
54+
// Generate another key stream
55+
BitSet secondKeyStream = keyStreamGenerator.getNextKeyStream();
56+
57+
// Assert that consecutive key streams are different
58+
assertNotEquals(firstKeyStream, secondKeyStream, "Consecutive key streams should be different");
59+
}
60+
}

0 commit comments

Comments
 (0)