格密码学习

格 Lattice

给定一组线性无关的基向量v1, v2, ..., vn,那么这些基向量的所有整系数线性组合
a 1 v 1 + a 2 v 2 + ⋯ + a n v n , a i ∈ Z \LARGE a_1 v_1+a_2 v_2+\cdots+a_n v_n, \quad a_i \in \mathbb{Z} a1v1+a2v2++anvn,aiZ
所形成的集合,就叫做这组基向量所张成的格(lattice)。(空间(span))

系数不再是任何实数,变成了是任何整数

从无数个连续的点变成了无数个离散的点,基底 i ⃗ = ( 1 , 0 ) , j ⃗ = ( 0 , 1 ) \vec{i}=(1,0),\vec{j}=(0,1) i =(1,0),j =(0,1)

离散
对原基底进行整系数线性转换得到的新的基底,张成的lattice仍旧不变:
[ i ′ j ′ ] = [ 1 1 − 2 − 1 ] = [ 1 1 − 2 − 1 ] [ 1 0 0 1 ] = T [ i j ] \left[\begin{array}{c} i^{\prime} \\ j^{\prime} \end{array}\right]=\left[\begin{array}{cc} 1 & 1 \\ -2 & -1 \end{array}\right]=\left[\begin{array}{cc} 1 & 1 \\ -2 & -1 \end{array}\right]\left[\begin{array}{ll} 1 & 0 \\ 0 & 1 \end{array}\right]=T\left[\begin{array}{l} i \\ j \end{array}\right] [ij]=[1211]=[1211][1001]=T[ij]
新的基底 i ′ ⃗ = ( 1 , 1 ) , j ′ ⃗ = ( − 2 , − 1 ) \vec{i'}=(1,1),\vec{j'}=(-2,-1) i =(1,1),j =(2,1)
置换

例子123

EX1 基础题目

题目

from Crypto.Util.number import *
import gmpy2
from flag import flag


def generate():
    p = getStrongPrime(2048)
    while True:
        f = getRandomNBitInteger(1024)
        g = getStrongPrime(768)
        h = gmpy2.invert(f, p) * g % p
        return (p, f, g, h)


def encrypt(plaintext, p, h):
    m = bytes_to_long(plaintext)
    r = getRandomNBitInteger(1024)
    c = (r * h + m) % p
    return c


p, f, g, h = generate()
c = encrypt(flag, p, h)
with open("cipher.txt", "w") as f:
    f.write("h = " + str(h) + "\n")
    f.write("p = " + str(p) + "\n")
    f.write("c = " + str(c) + "\n")

这道题目可以对应一个脆弱的密码方案

密钥生成过程:

  • p: 一个2048-bit的强素数 (“强”在于p-1p+1都至少有一个很大的素因数,以防某些攻击)
  • f:一个1024-bit的随机数
  • g:一个768-bit的强素数

f < p / 2 , p / 4 < g < p / 2 , gcd ⁡ ( f , p g ) = 1 f<\sqrt{p / 2}, \quad \sqrt{p / 4}<g<\sqrt{p / 2}, \quad \operatorname{gcd}(f, p g)=1 f<p/2 ,p/4 <g<p/2 ,gcd(f,pg)=1

f,g远小于p 且f与p,g互质,其次 $ h \equiv f^{-1} \cdot g \quad(\bmod p) (1)$ ,可以估算出h大小与p接近,O§级别,2000bit;

加密过程:

生成了一个1024bit的随机数r,计算密文 c ≡ r ⋅ h + m (   m o d   p ) ( 2 ) c \equiv r \cdot h+m \quad(\bmod p) (2) crh+m(modp)2

已知h,p,c ,理论上知道r即可以求解m,但随机数r无法直接求得

所以换个思路,从f,g出发做文章

解密过程:

将同余式(1)代入(2),并对式子两边同乘f,得到
c ⋅ f ≡ r ⋅ g + m ⋅ f (   m o d   p ) (3) c \cdot f \equiv r \cdot g+m \cdot f \quad(\bmod p)\tag 3 cfrg+mf(modp)(3)
根据大小关系可推知, r g + f m < p 2 p 2 + p 2 p 4 < p r g+f m<\sqrt{\frac{p}{2}} \sqrt{\frac{p}{2}}+\sqrt{\frac{p}{2}} \sqrt{\frac{p}{4}}<\boldsymbol{p} rg+fm<2p 2p +2p 4p <p

因此可以得到一个等式 $a= rg+fm $ ,对等式取模g,得到 a ≡ m ⋅ f (   m o d   g ) a \equiv m \cdot f \quad(\bmod g) amf(modg)

由此可以发现只需要得到f,g 就可以得到m, m ≡ a ⋅ f − 1 (   m o d   g ) m \equiv a \cdot f^{-1} \quad(\bmod g) maf1(modg)

p.s

  • 这里是在mod g下运算,还记得g是一个768-bit的强素数么?这就保证了,虽然f是个1024-bit的数,但是在mod g下,f' = f - k*g的逆元必定存在。
  • 此处的 f − 1 ( m o d g ) f^{-1}(mod g) f1(modg)h = f^-1 * g (mod p)里的不是同一个东西。
  • g有768-bit,768/8=96,flag字符串一般来说不会超过96个字符长,因此mg小,所以最终算出来的就是完完整整m

利用格求解

求解 h ≡ f − 1 ⋅ g (   m o d   p ) \Large h \equiv f^{-1} \cdot g \quad(\bmod p) hf1g(modp) ,即 f ⋅ h ≡ g (   m o d   p ) \Large f \cdot h \equiv g \quad(\bmod p) fhg(modp)

由下面这个矩阵M中的两个行向量(1,h), (0,p)所张成的lattice
M = [ 1 h 0 p ] M=\left[\begin{array}{ll} 1 & h \\ 0 & p \end{array}\right] M=[10hp]
证明向量**(f, g)**是在这个lattice上的

Proof:

首先将同余式改写成等式 f ⋅ h = g + u ⋅ p   → f ⋅ h − u ⋅ p = g \large f \cdot h=g+u \cdot p ~\rightarrow f \cdot h-u \cdot p=g fh=g+up fhup=g 可以得到
( f , − u ) M = ( f , − u ) [ 1 h 0 p ] = ( f + ( − u ) ⋅ 0 , f ⋅ h + ( − u ) ⋅ p ) = ( f , f ⋅ h − u ⋅ p ) = ( f , g ) \Large \begin{aligned} (f,-u) M &=(f,-u)\left[\begin{array}{ll} 1 & h \\ 0 & p \end{array}\right] \\ &=(f+(-u) \cdot 0, f \cdot h+(-u) \cdot p) \\ &=(f, f \cdot h-u \cdot p) \\ &=(f, g) \end{aligned} (f,u)M=(f,u) 10hp =(f+(u)0,fh+(u)p)=(f,fhup)=(f,g)
向量(f,g)可以由两组基向量M的某种整系数线性组合(f, -u)来表示,因此向量(f,g)就在这个lattice上。

看看h,p,f,g大小

  • h:2000多bit
  • p:2048-bit
  • f:1024-bit
  • g:768-bit

相对于两个基底向量(1, h), (0, p)来说,向量(f, g)的长度要小得多得多:

根据Gaussian heurstic可知,在这个lattice中最短向量的长度大概在sqrt(2^2048)=2^1024左右。因此,很大概率上,这个(f, g)就是这个lattice的最短向量

可见,一开始参数的大小设置,是很关键的一点。

Ex2: 子集合问题-(背包问题)4

SVP(最短向量问题)

  1. Gauss Lattice Reduction

    L是由两个基向量v1, v2所张成的2维lattice,假定|v1| < |v2|,我们现在通过减去v1的某个倍数来使得v2变短。
    v 2 ∗ = v 2 − v 1 ⋅ v 2 ∥ v 1 ∥ 2 v 1 \Large v_2^*=v_2-\frac{v_1 \cdot v_2}{\left\|v_1\right\|^2} v_1 v2=v2 v1 2v1v2v1
    得到一个与v1正交(垂直)的新向量v2*,且使得v2变短了

v1v2
在格里面只能减去整数倍的v1,如果v1 > v2,那么交换v1, v2,继续;否则,就结束。
v 2 − m v 1  with  m = ⌊ v 1 ⋅ v 2 ∥ v 1 ∥ 2 ⌉ v_2-m v_1 \quad \text { with } \quad m=\left\lfloor\frac{v_1 \cdot v_2}{\left\|v_1\right\|^2}\right\rceil v2mv1 with m=v12v1v2

  1. LLL算法

    sage中自带

# sage

def GaussLatticeReduction(v1, v2):
    while True:
        if v2.norm() < v1.norm():
            v1, v2 = v2, v1
        m = round( v1*v2 / v1.norm()^2 )
        if m == 0:
            return (v1, v2)
        v2 = v2 - m*v1

h = 7257231567493321493497732423756001924698993879741072696808433246581786362611889417289029671240997843541696187487722285762633068287623369923457879458577466240950224087015909821079480431797917376609839097610864517760515986973340148901898582075413756737310797402537478388864632901178463429574227279668004092519322204990617969134092793157225082977967228366838748193084097651575835471869030934527383379794480007872562067799484905159381690179011192017159985260435844246766711550315143517066359521598424992244464723490166447105679062078049379153154659732304112563255058750656946353654402824529058734270363154894216317570784
p = 23969137365202547728693945383611572667294904799854243194734466236017441545927679469239814785947383727854265554138290421827510545078908517696536495567625593439996528098119344504866817224169113920532528233185011693829122447604993468817512696036673804626830507903206709121383065701222707251053362179946170981868061834734684494881504724254812067180384269711822738708203454131838741703416329765575995359232573740932069147491776326045743679105041246906081872936901848272288949389026129761726749334006319072981386763830897454245553866145620689939497868469730297795063648030738668273210516497399954626983672357236110363894081
c = 6388077150013017095358415295704360631706672647932184267739118115740221804173068089559645506533240372483689997499821300861865955720630884024099415936433339512125910973936154713306915269365877588850574948033131161679256849814325373882706559635563285860782658950169507940368219930971600522754831612134153314448445006958300840618894359885321144158064446236744722180819829183828290798747455324761671198097712539900569386477647697973195787663298318786718012522378981137877863153067057280649127202971806609339007027052518049995341356359016898069863799529357397514218249272201695539181908803360181347114492616706419618151757

# Construct lattice.
v1 = vector(ZZ, [1, h])
v2 = vector(ZZ, [0, p])
m = matrix([v1,v2]);

# Solve SVP.
shortest_vector = m.LLL()[0]
# shortest_vector = GaussLatticeReduction(v1, v2)[0]
f, g = shortest_vector
print(f, g)

# Decrypt.
a = f*c % p % g
m = a * inverse_mod(f, g) % g
print(hex(m).decode('hex'))

# flag{c3bb1f88-2c0b-48fc-9902-beada6d50df6}

参考链接:


  1. 从一道CTF题初探NTRU格密码 - 先知社区 (aliyun.com) ↩︎

  2. 格密码笔记(一) (ruanx.net) ↩︎

  3. 浅尝 Lattice 之 HNP-安全客 - 安全资讯平台 (anquanke.com) ↩︎

  4. 格密码笔记(二) (ruanx.net) ↩︎

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值