关于求解线性序列的极小多项式和线性复杂度的BM算法实操理解
在流密码中,线性反馈移位寄存器(LFSR)是非常重要部件。学过线性移位寄存器序列相关知识的朋友都知道,Berlekamp-Massey算法(以下简称BM算法)是求解序列的线性复杂度的有效的方法。网上有很多BM算法的流程,笔者在学习的时候,感觉对着流程能够计算序列的线性复杂度,但是如果是闭卷考试,这个过程也太难记住了!所以本篇重新理解了一下BM算法的求解流程,重在教你如何快速掌握BM算法的计算过程。 如果你已经了解BM算法,你可以直接看第3点。
1、简介
N N N是一个正整数, a ( N ) = a 0 a 1 ⋯ a N − 1 a^{(N)}=a_{0}a_{1}\cdots a_{N-1} a(N)=a0a1⋯aN−1是有限域 F q F_{q} Fq上的一个长度为 N N N的序列, f N ( x ) f_{N}(x) fN(x)是一个能够产生 a ( N ) a^{(N)} a(N)且阶数最小的线性移位寄存器的联接多项式 , l N l_{N} lN是该线性反馈移位寄存器的阶数(也称作该序列的线性复杂度 )。我们称二元组 ( f N ( x ) , l N ) (f_{N}(x),l_{N}) (fN(x),lN)是 a ( N ) a^{(N)} a(N)的线性综合解 。另外,约定:0阶线性移位寄存器的联接多项式为 f ( x ) = 1 , l N = 0 f(x)=1,l_{N}=0 f(x)=1,lN=0,且长度为 n ( ≤ N ) n(\le N) n(≤N)的零序列 000 ⋯ 0 000\cdots0 000⋯0由0阶的线性移位寄存器产生。
注意BM算法求的是联接多项式,要想得到生成多项式,可以根据“联接多项式和生成多项式为互反多项式“得出来。
2、BM算法的流程
算法流程不清楚的可以在网上搜一搜,有很多。
3、如何理解算法流程
(理解这里的算法可以结合上述步骤来理解,多看几遍就会懂)首先,对上述算法中的几个符号做好理解。序列是 a ( N ) = a 0 a 1 ⋯ a N − 1 a^{(N)}=a_{0}a_{1}\cdots a_{N-1} a(N)=a0a1⋯aN−1,比如序列00101101中, a 0 = 0 , a 1 = 0 , a 2 = 1 ⋯ a_{0}=0,a_{1}=0,a_{2}=1\cdots a0=0,a1=0,a2=1⋯,为了规范计算,采用下标从0开始,但是在理解的时候,下标不再是从0开始,而是从1开始(这仅是个人的总结,你亦可以有自己的理解)。对每次迭代,要计算 f , l , d f,l,d f,l,d,这里, f i f_{i} fi表示生成前 i i i个字符的最小联接多项式, l i l_{i} li表示 f i f_{i} fi对应的LFSR的阶数, d i d_{i} di表示第 i + 1 i+1 i+1个字符能否由 ( f i , l i ) (f_{i},l_{i}) (fi,li)生成,若能生成, d i = 0 d_{i}=0 di=0,否则, d i = 1 d_{i}=1 di=1 。如果你没有理解,没关系,我们通过实例来看看到底是怎么做的。
以二元序列 00101101 00101101 00101101为例,首先,因为前2个字符都是0,根据简介中的约定,生成前0个字符的联接多项式,生成前1个字符的联接多项式,生成前2个字符的联接多项式都为1,即 f 0 ( x ) = f 1 ( x ) = f 2 ( x ) = 1 f_{0}(x)=f_{1}(x)=f_{2}(x)=1 f0(x)=f1(x)=f2(x)=1,当然它们对应的LFSR的长度为0,即 l 0 = l 1 = l 2 = 0 l_{0}=l_{1}=l_{2}=0 l0=l1=l2=0。那么 d 0 d_{0} d0等于什么呢?根据上述理解, d 0 d_{0} d0表示第1个字符能否由 ( f 0 , l 0 ) (f_{0},l_{0}) (f0,l0)生成,显然可以(第1个字符为 a 0 = 0 a_{0}=0 a0=0)。同理, d 1 d_{1} d1表示第2个字符能否由 ( f 1 , l 1 ) (f_{1},l_{1}) (f1,l1)生成,第2个字符 a 1 = 0 a_{1}=0 a1=0,是可以生成的,所以 d 1 = 0 d_{1}=0 d1=0。第3个字符是1,不能由 ( f 2 = 1 , l 2 = 0 ) (f_{2}=1,l_{2}=0) (f2=1,l2=0)生成(注意这是联接多项式),所以 d 2 = 1 d_{2}=1 d2=1。那 ( f 2 , l 2 ) (f_{2},l_{2}) (f2,l2)不能生成第三个字符了,我们就要找第三个字符的综合解,由于前面都是0,第三个字符才是1,所以我们找一个3级的寄存器,直接把 ( a 0 , a 1 , a 2 ) (a_{0},a_{1},a_{2}) (a0,a1,a2)作初始状态,这自然可以生成前3个字符。通常为了统一规定,我们认为是 f 3 = x 3 + 1 , l 3 = 3 f_{3}=x^{3}+1,l_{3}=3 f3=x3+1,l3=3。得到 ( f 3 , l 3 ) (f_{3},l_{3}) (f3,l3)了,我们就可以进一步计算 d 3 d_{3} d3,进而确定 ( f 4 , l 4 ) (f_{4},l_{4}) (f4,l4)。在这里,需要强调的是,只有第一个不为零的字符那里的多项式是这么规定的,比如这里的 f 3 f_{3} f3,但是后续的 d i = 1 d_{i}=1 di=1时,不是这么规定了,而是利用一个公式确定(上述流程中的最后那个更新公式) 。
其实这么看来,BM算法就是从第一个字符开始找,求出生成第一个字符的序列的线性综合解;然后再看这个线性综合解能不能继续生成第2个字符,也就是说这个线性综合解是不是前2个字符的线性综合解,如果是的,继续看第三个字符;如果不是的,则需要去寻找新的综合解。那么如何寻找新的综合解?根据上面说的,第一个非零字符的综合解是自己定(即第一个 a n 0 ≠ 0 a_{n0}\neq 0 an0=0时, f n 0 + 1 = x n 0 + 1 + 1 f_{n_{0}+1}=x^{n_{0}+1}+1 fn0+1=xn0+1+1),后续每个利用 f n + 1 = f n + x n − m f m f_{n+1}=f_{n}+x^{n-m}f_{m} fn+1=fn+xn−mfm来确定,这里的 m m m是根据 l l l的值来确定的,找到当前已经得到的所有 l l l中最近的那个跳跃的 l m l_{m} lm。我们可以继续上面那个例子:
已经求出了 f 3 , l 3 f_{3},l_{3} f3,l3,看能不能由此生成第四个字符,可以看出,如果利用 f 3 = x 3 + 1 f_{3}=x^{3}+1 f3=x3+1,生成的第四个字符是0,确实等于第四个字符,所以 d 3 = 0 , f 4 = f 3 = x 3 + 1 , l 4 = l 3 = 3 d_{3}=0,f_{4}=f_{3}=x^{3}+1,l_{4}=l_{3}=3 d3=0,f4=f3=x3+1,l4=l3=3。再计算 d 4 d_{4} d4:由 f 4 f_{4} f4生成的第五个字符是0,但是实际上第五个字符 a 4 = 1 a_{4}=1 a4=1,所以 d 4 = 1 d_{4}=1 d4=1,此时 l 4 = l 3 = 3 ≠ l 2 = l 1 = l 0 = 0 l_{4}=l_{3}=3\ne l_{2}=l_{1}=l_{0}=0 l4=l3=3=l2=l1=l0=0,所以从 l 4 l_{4} l4开始往前看,发现 l 2 l_{2} l2是最近(最后)一个跳跃的(即不相等),所以 m = 2 , n = 4 m=2,n=4 m=2,n=4,即 f 5 = f 4 + x 4 − 2 f 2 = x 3 + x 2 + 1 f_{5}=f_{4}+x^{4-2}f_{2}=x^{3}+x^{2}+1 f5=f4+x4−2f2=x3+x2+1, l 5 = m a x ( l 4 , 5 − l 4 ) = 3 l_{5}=max(l_{4},5-l_{4})=3 l5=max(l4,5−l4)=3。进一步计算,第六个字符1确实可以由 ( f 5 , l 5 ) (f_{5},l_{5}) (f5,l5)生成,所以 d 5 = 0 , f 6 = f 5 , l 6 = l 5 d_{5}=0,f_{6}=f_{5},l_{6}=l_{5} d5=0,f6=f5,l6=l5。 d 6 = 1 , f 7 = f 6 + x 6 − 2 f 2 = x 4 + x 3 + x 2 + 1 d_{6}=1,f_{7}=f_{6}+x^{6-2}f_{2}=x^{4}+x^{3}+x^{2}+1 d6=1,f7=f6+x6−2f2=x4+x3+x2+1, l 7 = m a x ( l 6 , 7 − l 6 ) = 4 l_{7}=max(l_{6},7-l_{6})=4 l7=max(l6,7−l6)=4。 d 7 = 1 , f 8 = f 7 + x 7 − 6 f 6 = x 2 + x + 1 , l 8 = m a x ( l 7 , 8 − l 7 ) = 4 d_{7}=1,f_{8}=f_{7}+x^{7-6}f_{6}=x^{2}+x+1,l_{8}=max(l_{7},8-l_{7})=4 d7=1,f8=f7+x7−6f6=x2+x+1,l8=max(l7,8−l7)=4.所以 a ( 8 ) = 00101101 a^{(8)}=00101101 a(8)=00101101的线性综合解是 ( 1 + x + x 2 , 4 ) (1+x+x^{2},4) (1+x+x2,4),对应的特征多项式是 F ( x ) = x 4 f ( 1 x ) = x 4 + x 3 + x 2 F(x)=x^{4}f(\frac{1}{x})=x^{4}+x^{3}+x^{2} F(x)=x4f(x1)=x4+x3+x2.
4、总结
大家可以细细理解一下过程,本篇目的不是讲算法原理和证明,是结合作者自身体验以理解性记忆的方式帮助大家记住BM算法的流程。
5、附BM算法的Python程序(二元序列)
if __name__ == '__main__':
q = 2
a = [0,0,1,0,1,1,0,1]
d = []
f = []
l = []
for i in range(len(a)+1):
d.append(-100000)
f.append([])
l.append(-100000)
f[0] = [1]
l[0] = 0
for n0 in range(len(a)):
if a[n0] != 0:
break
for i in range(n0):
d[i] = 0
d[n0] = a[n0]
for i in range(1,n0+1):
f[i] = [1]
l[i] = 0
temp_f = [1]
for i in range(1, n0+1):
temp_f.append(0)
temp_f.append(0-d[n0])
f[n0+1] = temp_f
l[n0+1] = n0 + 1
for n in range(n0+1, len(a)):
d[n] = 0
for i in range(l[n]+1):
d[n] += a[n-i]*f[n][i]
d[n] = d[n] % q
if d[n] == 0:
f[n+1] = f[n]
l[n+1] = l[n]
else:
for m in range(n-1,-1,-1):
if l[m] < l[m+1]:
break
l[n+1] = max(l[n], n+1-l[n])
temp_f = []
temp_fn = f[n].copy()
temp_fm = f[m].copy()
for i in range(l[n+1]+1):
if i > l[n]:
temp_fn.append(0)
if i > l[m]:
temp_fm.append(0)
k = n-m
pre = []
for i in range(k):
pre.append(0)
pre.extend(temp_fm[0:l[n+1]+1-k])
temp_fm = pre
f[n+1] = []
for i in range(l[n+1]+1):
f[n+1].append(temp_fn[i] - temp_fm[i])
print('f(x):',f)
print('l:',l)
print('d:',d)
结果是:
f(x): [[1], [1], [1], [1, 0, 0, -1], [1, 0, 0, -1], [1, 0, -1, -1], [1, 0, -1, -1], [1, 0, -1, -1, -1], [1, -1, -1, 0, 0]]
#这个表示系数,如最后的[1,-1,-1,0,0]表示多项式1+x+x^2,系数是模2的
l: [0, 0, 0, 3, 3, 3, 3, 4, 4]
d: [0, 0, 1, 0, 1, 0, 1, 1, -100000]
[Finished in 0.1s]