【入门建议收藏】密码学学习笔记之线性分析入门篇——EzSPN

本文介绍了线性分析作为已知明文攻击方法,通过寻找线性逼近表达式来区分分组密码与随机置换。文章以[NPUCTF2020]EzSPN题目为例,详细阐述了线性分析的步骤,包括寻找线性特征、建立线性区分器和密钥恢复攻击。通过分析加密流程,展示了如何利用线性分析对分组密码进行攻击,从而揭示了线性分析在密码学中的应用。
摘要由CSDN通过智能技术生成

前言

上一篇了解了一下差分分析,这次我们结合一道CTF题目聊一聊线性分析

同属于选择明文的差分分析不同,线性分析属于已知明文攻击方法,它通过寻找明文和密文之间的一个“有效”的线性逼近表达式,将分组密码与随机置换区分开来,并再此基础上进行密钥恢复攻击。

在正式介绍线性分析之前,我们还是要介绍一下相关的基础概念,参考《分组密码的攻击方法与实例分析》一书
在这里插入图片描述

基础概念

首先还是给出和差分分析一样的一个迭代分组密码的加密流程

迭代分组密码的加密流程
在这里插入图片描述
内积
在这里插入图片描述
线性掩码
在这里插入图片描述
线性逼近表达式
在这里插入图片描述
线性壳

迭代分组密码的一条 i 轮线性壳是指一对掩码(β0,βi),其中β0 是输入掩码,βi 是输出掩码。

线性特征
在这里插入图片描述
线性壳的线性概率
在这里插入图片描述
线性特征的线性概率
在这里插入图片描述
在这里插入图片描述

线性区分器

先给出一个命题,对{0,1}^n 上的随机置换R,任意给定掩码α,β,α ≠ 0,β ≠ 0, 则 LP(α,β ) = 0,​ 即 偏差 ε​(α,β) = 0

如果我们找到了一条 r-1 轮线性逼近表达式 (α,β),其线性概率 LP(α,β) ≠ 0,即偏差 ε(α,β) ≠ 0。则利用该线性逼近表达式可以将 r-1 轮的加密算法与随即置换区分开来,利用该线性区分器就可以对分组密码进行密钥恢复攻击。假设攻击 r 轮加密算法,为获得第 r 轮的轮密钥的攻击步骤如下。
步骤1

寻找一个 r – 1轮的线性逼近表达式 (α,β) ,设其偏差为ε(α,β),使得 |ε(α,β)|较大。

步骤2

根据区分器的输出,攻击者确定要恢复的第 r 轮轮密钥 k_r(或者其部分比特):设攻击的密钥比特长度为 l,对每个可能的候选密钥gk_i, 0 ≤ i ≤ 2^l -1,设置相应的 2^l 个计数器λ_i,并初始化。

步骤3

均匀随机地选取明文 X,在同一个未知密钥 k 下加密,(一般是让拥有密钥地服务端帮你加密)获得相应地密文 Z, 这里选择明文地数目为 m ≈ c ·(1/ε ^2),c 为某个常数。

步骤4

对一个密文Z,我们用自己猜测地第 r 轮轮密钥 gk_i(或其部分比特)对其进行第 r 轮解密得到Y_{r-1},然后我们计算线性逼近表达式 α x · X ⊕ β · Y_{r-1} 是否为0,若成立,则给相应计数器λ_i 加 1

步骤5

将 2^l 个计数器中|λ/m – 1/2| 最大地指所对应地密钥 gk_i(或其部分比特)作为攻击获得地正确密钥值。

Remark 针对步骤1中,我们如何去寻找一个高概率地 r -1 轮线性逼近表达式呢?例如针对一个S盒,我们可以选择穷举所有的输入、并获得相应的输出,然后穷举输入掩码、输出掩码,去获取这个S盒的相关线性特性。

下面就根据一道CTF中出现的赛题来解释分析上述过程。
在这里插入图片描述

实例-[NPUCTF2020]EzSPN

task.py

import os
from binascii import hexlify, unhexlify
import Crypto.Random.random as random
from secret import flag

SZ = 8
coef = [239, 163, 147, 71, 163, 75, 219, 73]
sbox = list(range(256))
random.shuffle(sbox)
sboxi = []
for i in range(256):
    sboxi.append(sbox.index(i))


def doxor(l1,l2):
    return [x[0]^x[1] for x in zip(l1,l2)]


def trans(blk):
    res = []
    for k in range(0, SZ, 8):
        bits = [bin(x)[2:].rjust(8,'0') for x in blk[k:k+8]]
        for i in range(8):
            res.append(int(''.join([x[(i+1) % 8] for x in bits]),2))
        res[k:k+8] = [(coef[i] * res[k+i]) % 256 for i in range(8)]
    return res


def encrypt_block(pt, ks):
    cur = doxor(pt, ks[:SZ])
    cur = [sbox[x] for x in cur]
    cur = trans(cur)
    cur = [sboxi[x] for x in cur]
    cur = doxor(cur, ks[SZ:])
    return cur


def encrypt(pt, k):
    x = 0 if len(pt)%SZ==0 else (SZ-len(pt)%SZ)
    pt += [x]*x
    ct = ''
    for i in range(0, len(pt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值