Edit
Does the state register (the LFSR) always have to remain with 16 bits (I'm assuming yes).
If so, are we shifting the register right by one (lfsr>>1
) and inserting the output bit onto the left-most bit (lfsr>>1 | bit<<15
) which allows us to wraparound within the same 16-bit address space.
So with this in mind, how does one generate the continuous keystream given:
seed: 1100101001110101
taps: 3, 12, 14, 15
Assuming you are given the following information:
Seed: 1100101001110101
Key Fragment: 000100011110101100001101101111101
And the following ciphertext/encrypted stream: 10101011000000010010110011001100101000010101010101010111101111110111010000010011
I am seemingly unable to decrypt the entire text into some ASCII values (UTF-8 decoded). I initially wrote a Berlekamp-Massey implementation and an online calculator to grab the tap positions of the above key fragment, which returned the following polynomial:
$$x^{15} + x^{14}+x^{12}+x^{3}+1$$
Fibonacci LFSR implemented in Rust:
fn next(&mut self) -> Option<(u16, u16)> {
self.bit = ((self.lfsr >> self.taps[0]) ^ (self.lfsr >> self.taps[1]) ^
(self.lfsr >> self.taps[2]) ^ (self.lfsr >> self.taps[3])) & 1;
self.lfsr = (self.lfsr >> 1) | (self.bit << 15);
if self.lfsr != self.seed {
Some((self.bit, self.lfsr))
} else {
None
}
}
- The key fragment never appears in the generated key stream, indicating something probably went wrong.
- The decrypted cipher doesn't map to ASCII values, just cryptic UTF-8 symbols.
The Berlekamp-Massey implementation is based off of the following whitepaper - https://www.osti.gov/servlets/purl/12658
And the full code can be found here - https://gist.github.com/JuxhinDB/ef8dac92b5af5de2e365d326b8dbc410