crypto-[中等偏下] 线性反馈移位寄存器(xctf)

随机数题,LFSR变形,记录一下。
题目源码:

from secret import secret
for b in secret: assert(b == '0' or b == '1')
assert(len(secret) == 128)
# a 01 string with length 128
# your flag is flag{md5(secret).hexdigest()}

def string2bits(s):
    return [int(b) for b in s]

def bits2string(bs):
    s = [str(b) for b in bs]
    return ''.join(s)

def lfsr(state, mask):
    assert(len(state) == 128)
    assert(len(mask)  == 128)

    output = 0
    for i in range(128):
        output = output ^ (state[i] & mask[i])

    return output

if __name__ == '__main__':
    initState = [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
    mask = string2bits(secret)

    for i in range(256):
        state = initState[i:]
        output = lfsr(state, mask)
        initState += [output]

    outputState = bits2string(initState[128:])
    print('outputState =', outputState)
    #
    # outputState = 1010100001001011101000000100100001101011010100101011010101011010100100001110010010110111010111110000000000011011001110100011000111110100110011011011100111000000001100001000001011010011011010110110111100110101001110001001001000001110111011110001111001111111
    #

分析一下题目逻辑。初识化数组 initState ,即为LFSR(线性反馈移位寄存器)的初始状态,mask 是flag转二进制之后的数组。

最主要的操作就是进行256轮LFSR计算,这地方和简单LFSR有点不同

  • lfsr函数,输入两个长度为128数组 state, mask ,输出 output 值为 o u t = ∑ s t a t e i × m a s k i m o d    2 out=\sum{state_i \times mask_i} \mod 2 out=statei×maskimod2
  • 注意到每轮 state 数组取值会向右移动一个位置,同时 initState 长度会增长1,即数组尾部追加了 output

关键的关系式 o u t = ∑ s t a t e i × m a s k i m o d    2 out=\sum{state_i \times mask_i} \mod 2 out=statei×maskimod2
可改写为矩阵乘法形式 o u t = S t a t e × M a s k m o d    2 out=State \times Mask \mod 2 out=State×Maskmod2
State是 1 × 128 1\times128 1×128 向量,Mask是 128 × 1 128 \times 1 128×1 向量

256轮循环最终输出 initState 数组后256个元素,命名为 outputState,其中 o u t p u t S t a t e 0...127 × M a s k = o u t p u t S t a t e 128 m o d    2 o u t p u t S t a t e 1...128 × M a s k = o u t p u t S t a t e 129 m o d    2 ⋯ o u t p u t S t a t e 127...254 × M a s k = o u t p u t S t a t e 255 m o d    2 outputState_{0...127} \times Mask = outputState_{128} \mod 2 \\ outputState_{1...128} \times Mask = outputState_{129} \mod 2 \\ \cdots \\ outputState_{127...254} \times Mask = outputState_{255} \mod 2 outputState0...127×Mask=outputState128mod2outputState1...128×Mask=outputState129mod2outputState127...254×Mask=outputState255mod2

尝试模2条件下线性方程组求解。
求解有点问题,最后是把initState组在outputState前面一起解方程组,得到正解

最终exp:

#sage
def string2bits(s):
    return [int(b) for b in s]

if __name__ == '__main__':
    initState = [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
    outputState = string2bits('1010100001001011101000000100100001101011010100101011010101011010100100001110010010110111010111110000000000011011001110100011000111110100110011011011100111000000001100001000001011010011011010110110111100110101001110001001001000001110111011110001111001111111')
    states = initState + outputState
    
    ms = MatrixSpace(GF(2), 128, 128)
    mv = []
    for i in range(128):
        mv += states[i : i + 128]
    m= ms(mv)
    
    vs = MatrixSpace(GF(2), 128, 1)
    vv = outputState[0:128]
    v = vs(vv)
    
    secret = m.inverse() * v
    M=secret.str().replace('\n','').replace('[','').replace(']','')
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值