ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Streamcipher Learning1

2022-02-02 20:31:45  阅读:135  来源: 互联网

标签:Learning1 lfsr self mask len range key Streamcipher


Streamcipher Learning

LFSR

简介

对于给定的初状态(a1 , ... ,an)和反馈函数f

[反馈函数一般为ai+n=\(\sum_{j=1}^nc_ja_{i+n-j}\)]

有f(ai , ... ,ai+n-1) = (ai+1 , ... ,ai+n)

考虑到f是线性函数,我们将其表示为矩阵的形式

=>(ai+1 , ... ,ai+n) = A(ai , ... ,ai+n-1)

而在学习了矩阵后我们知道移位运算,取位运算,异或运算均能看出线性变换,能够由矩阵乘法表示,这就将本来抽象的位运算转化为了熟悉的矩阵运算

对几种伪随机数生成器的分析都可能会用到这种思想

为了使得密钥流输出更加复杂,会对lfsr进行一些变化,使其成为非线性反馈移位寄存器,常见的有三种:

1.非线性组合生成器,对多个lfsr使用一个非线性组合函数

2.非线性滤波器,对一个lfsr输出使用一个非线性组合函数

3.钟控生成器,使用一个或多个lfsr控制其它lfsr输出

下面我们考虑lfsr的生成周期

通常N位的线性反馈寄存器最多有 2N个不同的状态。但是如果出现初值为N个0的情况,线性反馈寄存器陷入死循环,要排除掉。所以N位线性反馈寄存器能产生最长的不重复序列为 2N-1

引入线性变换的特征多项式f(x)=xn-\(\sum_{i=1}^{n}c_ix^{n-i}\)

定义互反多项式为f'(x)=xnf(\(\frac{1}{x}\))

已知某个n级线性反馈移位寄存器的特征多项式,那么该序列对应的生成函数为A(x)=\(\frac{p(x)}{f'(x)}\)

p(x)=\(\sum_{i=1}^n(c_{n-i}x^{n-i}\sum_{j=1}^ia_jx^{j-1})\)

序列的周期为生成函数既约真分式的分母的周期

达到最长周期的序列称为m序列

首先python实现一下lfsr的加密过程

实现

def lfsr(seed,mask):
    state=seed
    Mask=int(mask,2)
    statelen=2**len(mask)-1
    t=state&Mask
    out=0
    while t:
        out^=t&1
        t=t>>1
    state=(state<<1^out)&statelen
    return state,out

逆向

下面分别采用位运算和矩阵运算(本质是一样的)对lfsr进行逆向

我们已知生成的连续len(初态)的输出序列(这里为了方便使用(alen(初态)+1,···,a2len(初态)),和掩码

1.矩阵方式

c=''
mask=''
Mask=Matrix.zero(len(mask))
for i in range(len(mask)-1):
	Mask[i,i+1]=1
for i in range(len(mask)):
	Mask[len(mask)-1,i]=mask[i]
Mask=Matrix(GF(2),Mask)
v=[]
for i in range(len(c)):
	v.append(c[i])
V=vector(GF(2),v)
m=Mask^(-1)*V

2.位运算

c=''
c=int(c,2)
def backtrace(state, mask):
    mask=int(mask,2)
    mask = ((mask & (2**7-1)) << 1) + 1
    i = state & mask
    outPut = 0
    while i != 0:
        outPut ^= (i & 1)
        i = i >> 1
    state >>= 1
    return (outPut <<7) + state
for i in range(8):
    c=backtrace(c,mask)
print(bin(c)[2:].rjust(8,'0'))

在位运算操作的时候可以发现mask的首位不为0才能还原,用矩阵同样会发现当首位为1时矩阵是不满秩的,很显然因为第一列是全0的

示例

babylfsr

import hashlib
from secret import KEY,FLAG,MASK

assert(FLAG=="de1ctf{"+hashlib.sha256(hex(KEY)[2:].rstrip('L')).hexdigest()+"}")
assert(FLAG[7:11]=='1224')

LENGTH = 256

assert(KEY.bit_length()==LENGTH)
assert(MASK.bit_length()==LENGTH)

def pad(m):
    pad_length = 8 - len(m)
    return pad_length*'0'+m

class lfsr():
    def __init__(self, init, mask, length):
        self.init = init
        self.mask = mask
        self.lengthmask = 2**(length+1)-1

    def next(self):
        nextdata = (self.init << 1) & self.lengthmask 
        i = self.init & self.mask & self.lengthmask 
        output = 0
        while i != 0:
            output ^= (i & 1)
            i = i >> 1
        nextdata ^= output
        self.init = nextdata
        return output


if __name__=="__main__":
    l = lfsr(KEY,MASK,LENGTH)
    r = ''
    for i in range(63):
        b = 0
        for j in range(8):
            b = (b<<1)+l.next()
        r += pad(bin(b)[2:])
    with open('output','w') as f:
        f.write(r)
        
#001010010111101000001101101111010000001111011001101111011000100001100011111000010001100101110110011000001100111010111110000000111011000110111110001110111000010100110010011111100011010111101101101001110000010111011110010110010011101101010010100101011111011001111010000000001011000011000100000101111010001100000011010011010111001010010101101000110011001110111010000011010101111011110100011110011010000001100100101000010110100100100011001000101010001100000010000100111001110110101000000101011100000001100010

常见攻击方式:

给出2n个连续生成数据(ai , ... ,ai+2n-1)

记Sj=(ai+(j-1) , ... ,ai+(j-1)+n-1) (j=1,2,...,n+1)

构造矩阵X=[S1,S2,...,Sn] => Sn+1 = (c1 , ... ,cn)X =>(c1 , ... ,cn) =Sn+1 X-1

对所给数据爆破8位

import hashlib
c1='001010010111101000001101101111010000001111011001101111011000100001100011111000010001100101110110011000001100111010111110000000111011000110111110001110111000010100110010011111100011010111101101101001110000010111011110010110010011101101010010100101011111011001111010000000001011000011000100000101111010001100000011010011010111001010010101101000110011001110111010000011010101111011110100011110011010000001100100101000010110100100100011001000101010001100000010000100111001110110101000000101011100000001100010'
for i in range(256):
    c=c1+bin(i)[2:].rjust(8,'0')
    A=Matrix.zero(256)
    for i in range(256):
        for j in range(256):
            A[i,j]=c[i+j]
    G=GF(2)
    A=Matrix(G,A)
    v=[]
    for i in range(256,512):
        v.append(int(c[i]))
    V=Matrix(G,v)
    try:
        M=V*A^(-1)
        M=list(vector(M))
        maskM=Matrix.zero(256)
        for i in range(255):
            maskM[i,i+1]=1
        for i in range(256):
            maskM[255,i]=M[i]
        maskM=Matrix(G,maskM)
        V=vector(V)
        mask=maskM^512
        m=((mask)^(-1))*V
        key=''
        for i in range(256):
            key+=str(m[i])
        key=int(key,2)
        FLAG="de1ctf{"+hashlib.sha256(hex(key)[2:].rstrip('L').encode()).hexdigest()+"}"
        if FLAG[7:11]=='1224':
            print(FLAG)
    except:
        continue
    c=''

Tiny LFSR

import sys
from binascii import unhexlify

if(len(sys.argv)<4):
	print("Usage: python Encrypt.py keyfile plaintext ciphername")
	exit(1)

def lfsr(R, mask):
	output = (R << 1) & 0xffffffffffffffff
	i=(R&mask)&0xffffffffffffffff
	lastbit=0
	while i!=0:
		lastbit^=(i&1)
		i=i>>1
	output^=lastbit
	return (output,lastbit)

R = 0
key = ""
with open(sys.argv[1],"r") as f:
	key = f.read()
	R = int(key,16)
	f.close
	
mask = 0b1101100000000000000000000000000000000000000000000000000000000000

a = ''.join([chr(int(b, 16)) for b in [key[i:i+2] for i in range(0, len(key), 2)]])

f=open(sys.argv[2],"r")
ff = open(sys.argv[3],"wb")
s = f.read()
f.close()
lent = len(s)

for i in range(0, len(a)):
	ff.write((ord(s[i])^ord(a[i])).to_bytes(1, byteorder='big'))

for i in range(len(a), lent):
    tmp=0
    for j in range(8):
        (R,out)=lfsr(R,mask)
        tmp=(tmp << 1)^out
    ff.write((tmp^ord(s[i])).to_bytes(1, byteorder='big'))
ff.close()

此题并没有考lfsr的细节,因为异或的性质,我们只需爆破完key,重走一遍加密过程即可

代码如下

f=open('cipher.txt','rb')
ff=open('flag_encode.txt','rb')
pt='sdgfjkahblskdjxbvfskljdfbguisldfbvghkljsdfbghsjkldhbgjklsdbgvlkjsdgbkljb sdkljfhwelo;sdfghioeurthgbnjl k'
c=f.read()
flagc=ff.read()
mask = 0b1101100000000000000000000000000000000000000000000000000000000000
def lfsr(R, mask):
    output = (R << 1) & 0xffffffffffffffff
    i=(R&mask)&0xffffffffffffffff
    lastbit=0
    while i!=0:
        lastbit^=(i&1)
        i=i>>1
    output^=lastbit
    return (output,lastbit)

def decrypt1(key, c,m):
    for i in range(len(a)):
        m+=chr(c[i]^ord(key[i]))
    return m

def decrypt2(R,mask,m,c):
    for i in range(len(a),len(c)):
        tmp=0
        for j in range(8):
            (R,out)=lfsr(R,mask)
            tmp=(tmp<<1)^out
        m+=chr(c[i]^tmp)
    return m

for i in range(1,len(c)):
    a1=''
    for j in range(i):
        a1+=chr(c[j]^ord(pt[j]))
    key=''
    for i in range(len(a1)):
        key+=hex(ord(a1[i]))[2:].rjust(2,'0')
    R=int(key,16)
    a = ''.join([chr(int(b, 16)) for b in [key[i:i + 2] for i in range(0, len(key), 2)]])
    m=''
    m+=decrypt1(key,flagc,m)
    m+=decrypt2(R,mask,m,flagc)
    print(m)

FilterRandom[西湖论剑]

import random
from secret import init1,init2,flag
assert flag==b'DASCTF{%d-%d}'%(init1,init2)

class lfsr():
    def __init__(self, init, mask, length):
        self.init = init
        self.mask = mask
        self.lengthmask = 2**length-1

    def next(self):
        nextdata = (self.init << 1) & self.lengthmask 
        i = self.init & self.mask & self.lengthmask 
        output = 0
        while i != 0:
            output ^= (i & 1)
            i = i >> 1
        nextdata ^= output
        self.init = nextdata
        return output

def my_filter(c1,c2):
    if random.random()>0.1:
        return str(c1)
    else:
        return str(c2)

N=64
mask1=random.getrandbits(N)
mask2=random.getrandbits(N)
print(mask1)
print(mask2)
l1=lfsr(init1,mask1,N)
l2=lfsr(init2,mask2,N)
output=''
for i in range(2048):
    output+=my_filter(l1.next(),l2.next())
print(output)
'''
17638491756192425134
14623996511862197922
10001011010100011000100101001011100010110111001100001110000111011011100101101101000111101100010111100011000011111111010101111100101010101100010100000111011010011110111000100000101100101010110100111100011000101010101011011111011011000001101001011000010000011110001111001111011100110011111111101000111101001010000110001110111101001001101011101101001010001101010010110000000000001001101100101011110011010110011010110110011001001111001010100011110111100100010110111100110010000000010010011110001100000011000001110001000000010000100100101100000011100000011110101001011010011010100001101000010100100000011001011001000110000000000111011101000110010110111110010101110010001010001111111000011010000011001110111001000010011000000111010111100000100010011001111101110110100100011111000111000011111101010010110011111100010000100101011000001010101111101111001000011101111000111000101011010111100110001011011100101001010110110110110011100100111100110001101110010100010111100000110000010110100010001100011011001100100110101110010100011101110110010000010011100000011100000101010011011111110000100000010001010111011011111110100111100011100011110110010001011101111001011101010110111001001000111001001111001111110111111100001111100100110011111110110101000011010111110010001100000111100010011100011010000101010111010101101000011001110011000000110110110001101100110101110010010111011100110101000110000011001010100000110000000001110010001010001001101111100001111111011010010011100110010000111010001001111111110000010101110011010100100101101100111000010110100110010001010110111110011000111011101110100010000110110110011001011111011111000000000000001110000001000011000110111000000110100110110001111011111100010010011100101010000111000011111010000001010010011101010010110011000000001111110000000010111011000010001111000100110101110001000011111001101111111100011111011001001110000101001101110100111010011011101000110010000001001000001100110001110101100001000110100100010111101100010100110011111010011100100001101111010000110110101111111001111011100001101100000001101111100100
'''

第一次做带滤波的lfsr,调了一下午总算整出来了,一直给我卡在把sage的^当异或上

标签:Learning1,lfsr,self,mask,len,range,key,Streamcipher
来源: https://www.cnblogs.com/oyrd/p/15860705.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有