Package: pylfsr
LFSR -Linear Feedback Shift RegisterLinks:Github Page|Documentation|Github|PyPi - project|     _Installation:pip install pylfsrTable of contentsNew UpdatesInstallationExamples5-bit LFSRVizualize each statePlot your LFSRTest properties of LFSRA5/1 GSM Stream CipherGeffe GenegeratorMatlab ImplementationCite AsNew UpdatesPlot Your LFSR with pylfsrUpdates:Version: 1.0.7:Added Galois ConfigurationImproved DocumentationComputing LZ complexityVersion: 1.0.6:Fixed the bugs (1) missing initial bit (2) exceptionAdded test properties of LFSR(1) Balance Property(2) Runlength Property(3) Autocorrelation PropertyPloting function to display LFSRA5/1 GSM Stream Ciper GeneratorGeffe GeneratorInstallationRequirement :numpy,matplotlibwith pippip install pylfsrBuild from the sourceDownload the repository or clone it with git, after cd in directory build it from source withpython setup.py installExamplesExample 1: 5-bit LFSR with feedback polynomialx^5 + x^2 + 1# import LFSR
import numpy as np
from pylfsr import LFSR

L = LFSR()

# print the info
L.info()

5 bit LFSR with feedback polynomial  x^5 + x^2 + 1
Expected Period (if polynomial is primitive) =  31
Current :
State        :  [1 1 1 1 1]
Count        :  0
Output bit   : -1
feedback bit : -1L.next()
L.runKCycle(10)
L.runFullCycle()
L.info()Example 2**: 5-bit LFSR with custum state and feedback polynomialstate = [0,0,0,1,0]
fpoly = [5,4,3,2]
L = LFSR(fpoly=fpoly,initstate =state, verbose=True)
L.info()
tempseq = L.runKCycle(10)
L.set(fpoly=[5,3])Example 3 ## To visualize the process with 3-bit LFSR, with default counter_start_zero = Truestate = [1,1,1]
fpoly = [3,2]
L = LFSR(initstate=state,fpoly=fpoly)
print('count \t state \t\toutbit \t seq')
print('-'*50)
for _ in range(15):
    print(L.count,L.state,'',L.outbit,L.seq,sep='\t')
    L.next()
print('-'*50)
print('Output: ',L.seq)Output :count 	        state 		outbit 	 seq
--------------------------------------------------
0		[1 1 1]		-1	[-1]
1		[0 1 1]		1	[1]
2		[0 0 1]		1	[1 1]
3		[1 0 0]		1	[1 1 1]
4		[0 1 0]		0	[1 1 1 0]
5		[1 0 1]		0	[1 1 1 0 0]
6		[1 1 0]		1	[1 1 1 0 0 1]
7		[1 1 1]		0	[1 1 1 0 0 1 0]
8		[0 1 1]		1	[1 1 1 0 0 1 0 1]
9		[0 0 1]		1	[1 1 1 0 0 1 0 1 1]
10		[1 0 0]		1	[1 1 1 0 0 1 0 1 1 1]
11		[0 1 0]		0	[1 1 1 0 0 1 0 1 1 1 0]
12		[1 0 1]		0	[1 1 1 0 0 1 0 1 1 1 0 0]
13		[1 1 0]		1	[1 1 1 0 0 1 0 1 1 1 0 0 1]
14		[1 1 1]		0	[1 1 1 0 0 1 0 1 1 1 0 0 1 0]
--------------------------------------------------
Output:  [1 1 1 0 0 1 0 1 1 1 0 0 1 0 1]Example 4 ## To visualize the process with 3-bit LFSR, with default counter_start_zero = Falsestate = [1,1,1]
fpoly = [3,2]
L = LFSR(initstate=state,fpoly=fpoly,counter_start_zero=False)
print('count \t state \t\toutbit \t seq')
print('-'*50)
for _ in range(15):
    print(L.count,L.state,'',L.outbit,L.seq,sep='\t')
    L.next()
print('-'*50)
print('Output: ',L.seq)Outputcount 	 state 		outbit 	 seq
--------------------------------------------------
1	[1 1 1]		1	[1]
2	[0 1 1]		1	[1 1]
3	[0 0 1]		1	[1 1 1]
4	[1 0 0]		0	[1 1 1 0]
5	[0 1 0]		0	[1 1 1 0 0]
6	[1 0 1]		1	[1 1 1 0 0 1]
7	[1 1 0]		0	[1 1 1 0 0 1 0]
8	[1 1 1]		1	[1 1 1 0 0 1 0 1]
9	[0 1 1]		1	[1 1 1 0 0 1 0 1 1]
10	[0 0 1]		1	[1 1 1 0 0 1 0 1 1 1]
11	[1 0 0]		0	[1 1 1 0 0 1 0 1 1 1 0]
12	[0 1 0]		0	[1 1 1 0 0 1 0 1 1 1 0 0]
13	[1 0 1]		1	[1 1 1 0 0 1 0 1 1 1 0 0 1]
14	[1 1 0]		0	[1 1 1 0 0 1 0 1 1 1 0 0 1 0]
--------------------------------------------------
Output:  [1 1 1 0 0 1 0 1 1 1 0 0 1 0 1]Visualize & Plot LFSRL.Viz(show=False, show_labels=False,title='R1')Dynamic plot - Animation in notebook%matplotlib notebook
L = LFSR(initstate=[1,0,1,0,1],fpoly=[5,4,3,2],counter_start_zero=False)
fig, ax = plt.subplots(figsize=(8,3))
for _ in range(35):
  ax.clear()
  L.Viz(ax=ax, title='R1')
  plt.ylim([-0.1,None])
  #plt.tight_layout()
  L.next()
  fig.canvas.draw()
  plt.pause(0.1)Example 5  ## 23 bit LFSR with custum state and feedback polynomialfpoly = [23,19]
L1 = LFSR(fpoly=fpoly,initstate ='ones', verbose=False)
L1.info()Output23 bit LFSR with feedback polynomial  x^23 + x^19 + 1
Expected Period (if polynomial is primitive) =  8388607
Current :
 State        :  [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 Count        :  0
 Output bit   :  -1
 feedback bit :  -1seq = L1.runKCycle(100)array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1])Example 6 ## testing the propertiesstate = [1,1,1,1,0]
fpoly = [5,3]
L = LFSR(initstate=state,fpoly=fpoly)
result  = L.test_properties(verbose=2)Output1. Periodicity
------------------
 - Expected period = 2^M-1 = 31
 - Pass?:  True

2. Balance Property
-------------------
 - Number of 1s = Number of 0s+1 (in a period): (N1s,N0s) =  (16, 15)
 - Pass?:  True

3. Runlength Property
-------------------
 - Number of Runs in a period should be of specific order, e.g. [4,2,1,1]
 - Runs:  [8 4 2 1 1]
 - Pass?:  True

4. Autocorrelation Property
-------------------
 - Autocorrelation of a period should be noise-like, specifically, 1 at k=0, -1/m everywhere else
 - Pass?:  True

==================
Passed all the tests
==================Testing individual property# get a full period sequence
p = L.getFullPeriod()
p
array([0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0,
       0, 1, 0, 0, 1, 0, 1, 1, 0])L.balance_property(p.copy())
# (True, (16, 15))

L.runlength_property(p.copy())
# (True, array([8, 4, 2, 1, 1]))

L.autocorr_property(p.copy())[0]
#TrueExample 7 ## testing the properties for non-primitive polynomialstate = [1,1,1,1,0]
fpoly = [5,1]
L = LFSR(initstate=state,fpoly=fpoly)
result = L.test_properties(verbose=1)Output1. Periodicity
------------------
 - Expected period = 2^M-1 = 31
 - Pass?:  False

2. Balance Property
-------------------
 - Number of 1s = Number of 0s+1 (in a period): (N1s,N0s) =  (17, 14)
 - Pass?:  False

3. Runlength Property
-------------------
 - Number of Runs in a period should be of specific order, e.g. [4,2,1,1]
 - Runs:  [10  2  1  1  2]
 - Pass?:  False

4. Autocorrelation Property
-------------------
 - Autocorrelation of a period should be noise-like, specifically, 1 at k=0, -1/m everywhere else
 - Pass?:  False

==================
Failed one or more tests, check if feedback polynomial is primitive polynomial
==================Example 8**: Get the feedback polynomial or listReference :http://www.partow.net/programming/polynomials/index.htmlL = LFSR()
# list of 5-bit feedback polynomials
fpoly = L.get_fpolyList(m=5)

# list of all feedback polynomials as a dictionary
fpolyDict = L.get_fpolyList()Changing feedback polynomial in betweenL.changeFpoly(newfpoly =[23,14],reset=False)
seq1 = L.runKCycle(20)

# Change after 20 clocks
L.changeFpoly(newfpoly =[23,9],reset=False)
seq2 = L.runKCycle(20)GeneratorsA5/1 GSM Stream cipher generatorRef:https://en.wikipedia.org/wiki/A5/1import numpy as np
import matplotlib.pyplot as plt
from pylfsr import A5_1

A5 = A5_1(key='random')
print('key: ',A5.key)
A5.R1.Viz(title='R1')
A5.R2.Viz(title='R2')
A5.R3.Viz(title='R3')

print('key: ',A5.key)
print()
print('count \t cbit\t\tclk\t R1_R2_R3\toutbit \t seq')
print('-'*80)
for _ in range(15):
    print(A5.count,A5.getCbits(),A5.clock_bit,A5.getLastbits(),A5.outbit,A5.getSeq(),sep='\t')
    A5.next()
print('-'*80)
print('Output: ',A5.seq)

A5.runKCycle(1000)
A5.getSeq()Enhanced A5/1Reference Article:Enhancement of A5/1:https://doi.org/10.1109/ETNCC.2011.5958486# Three LFSRs initialzed with 'ones' though they are intialized with encription key
R1 = LFSR(fpoly = [19,18,17,14])
R2 = LFSR(fpoly = [23,22,21,8])
R3 = LFSR(fpoly = [22,21])

# clocking bits
b1 = R1.state[8]
b2 = R3.state[10]
b3 = R3.state[10]Geffe GeneratorRef: Schneier, Bruce. Applied cryptography: protocols, algorithms, and source code in C. john wiley & sons, 2007.
Chaper 16import numpy as np
import matplotlib.pyplot as plt
from pylfsr import Geffe, LFSR

kLFSR = [LFSR(initstate='random') for _ in range(8)]  # List of 8 5-bit LFSRs with default feedback polynomial and random initial state
cLFSR = LFSR(initstate='random')                      # A 5-bit LFSR with for selecting one of 8 output at a time

GG = Geffe(kLFSR_list=kLFSR, cLFSR=cLFSR)

print('key: ',GG.getState())
print()
for _ in range(50):
    print(GG.count,GG.m_count,GG.outbit_k,GG.sel_k,GG.outbit,GG.getSeq(),sep='\t')
    GG.next()

GG.runKCycle(1000)
GG.getSeq()MATLABFor matlab files download it from hereFolder :https://github.com/Nikeshbajaj/Linear_Feedback_Shift_Register/tree/master/matlabfilesDescriptionGenrate randon binary sequence using LFSR for any given feedback taps (polynomial),
This will also check Three fundamental Property of LFSRBalance PropertyRunlength PropertyAutocorrelation PropertyThis MATLAB Code work for any length of LFSR with given taps (feedback polynomial) -Universal, There are three files LFSRv1.m an LFSRv2.m, LFSRv3.mLFSRv1This function will return all the states of LFSR and will check Three fundamental Property of LFSR
(1) Balance Property (2) Runlength Property (3) Autocorrelation PropertyEXAMPLEs=[1 1 0 0 1]
t=[5 2]
[seq c] =LFSRv1(s,t)LFSRv2This function will return only generated sequence will all the states of LFSR, no verification of properties are done
here. Use this function to avoid verification each time you execute the program.EXAMPLEs=[1 1 0 0 1]
t=[5 2]
[seq c] =LFSRv2(s,t)LFSRv3 (faster)seq = LFSRv3(s,t,N)this function generates N bit sequence only. This is faster then other two functions, as this does not gives each state of LFSREXAMPLEs=[1 1 0 0 1]  
t=[5 2]
seq =LFSRv3(s,t,50)TipsIf you want to use this function in middle of any program, use LFSRv2 or LFSRv1 with verification =0.If you want to make it fast for long length of LFSR,use LFSRv3.mCite As@software{nikesh_bajaj_2021_4726667,
  author       = {Nikesh Bajaj},
  title        = {Nikeshbajaj/Linear\_Feedback\_Shift\_Register: 1.0.6},
  month        = apr,
  year         = 2021,
  publisher    = {Zenodo},
  version      = {1.0.6},
  doi          = {10.5281/zenodo.4726667},
  url          = {https://doi.org/10.5281/zenodo.4726667}
}Contacts:If any doubt, confusion or feedback please contact meNikesh Bajajhttp://nikeshbajaj.inn.bajaj@imperial.ac.ukn.bajaj@qmul.ac.ukbajaj[dot]nikkey[AT]gmail[dot]?PhD Student: Queen Mary University of London & University of Genoa