2023闽盾杯线上初赛Crypto wp

2023闽盾杯线上初赛 Crypto

这高职组比本科组难的可不是一点,建议做高职组的题,本科组看看就好

本科组


DDSA

就是dsa签名,然后私钥取值太小了,考虑用格解一下就出了。DSA签名

这题总结一下就一个式子
s = m ∗ ( H ( m ) + p r i ∗ r ) m o d    q p r i : 384 b i t s s , r , H ( m ) , q 已知 s=m*(H(m)+pri*r)\mod q\\ pri:384bits\\ s,r,H(m),q已知 s=m(H(m)+prir)modqpri:384bitss,r,H(m),q已知
这一看就像hnp

尝试1
s ∗ m − 1 ∗ r − 1 − H ( m ) ∗ r − 1 = p r i A = s ∗ r − 1 , B = H ( m ) ∗ r − 1 M = ( q A 2 384 / 2 1024 B 2 384 ) s*m^{-1}*r^{-1}-H(m)*r^{-1}=pri\\ A=s*r^{-1},B=H(m)*r^{-1}\\ M=\begin{pmatrix}q&&\\A&2^{384}/2^{1024}&\\ B &&2^{384}\end{pmatrix} sm1r1H(m)r1=priA=sr1,B=H(m)r1M= qAB2384/210242384

( k , m − 1 , − 1 ) ∗ M = ( p r i , C , 2 384 ) C = 2 384 ∗ m − 1 / 2 1024 = 384 b i t s (k,m^{-1},-1)*M=(pri,C,2^{384})\\ C=2^{384}*m^{-1}/2^{1024}=384bits (k,m1,1)M=(pri,C,2384)C=2384m1/21024=384bits

尝试失败,这里 m − 1 m^{-1} m1太大了,1024bits,而私钥 p r i pri pri只有384。


Solution

对于
A ∗ x + B = C m o d    P A*x+B=C\mod P Ax+B=CmodP
如果 x , C x,C x,C均是小bits,那么很容易求解

这里考虑 m m m是一个小于512bits,即小于64字节的flag。实际上最后算出来m很小很合理吧
H ( m ) − 1 ∗ s = m + H ( m ) − 1 ∗ r ∗ p r i ∗ m A = − H ( m ) − 1 ∗ r B = H ( m ) − 1 ∗ s A ∗ p r i ∗ m + B = m H(m)^{-1}*s=m+H(m)^{-1}*r*pri*m\\ A=-H(m)^{-1}*r\\ B=H(m)^{-1}*s\\ A*pri*m+B=m H(m)1s=m+H(m)1rprimA=H(m)1rB=H(m)1sAprim+B=m

p r i ∗ m < 512 + 384   b i t s m < 512   b i t s pri*m<512+384\ bits\\ m<512\ bits prim<512+384 bitsm<512 bits

M = ( q A 2 384 + 512 / 2 1024 B 2 512 ) M=\begin{pmatrix}q&&\\A&2^{384+512}/2^{1024}&\\ B &&2^{512}\end{pmatrix} M= qAB2384+512/210242512

实际上m<512bits也能格出来,但是最好是已知flag的长度,构造相应的格。可以把512换成 l e n ( f l a g ) ∗ 8 len(flag)*8 len(flag)8就好了

exp

prime_p = 254843759712120770192107797102254314236912507988317949449773952808056853528137124034192193635099026436082859359975257478069529928753465466553898924428657727410192480025664330547720267491593689914315716652925690802124634579341155119238992435231736067051804606192447508930100501670982605518547228404550199336703
prime_q = 127421879856060385096053898551127157118456253994158974724886976404028426764068562017096096817549513218041429679987628739034764964376732733276949462214328863705096240012832165273860133745796844957157858326462845401062317289670577559619496217615868033525902303096223754465050250835491302759273614202275099668351
generator = 2
public_key = 67243435243013084147486854556817234112402511481243660325565023251853355494433326575673419694681555652669449040366620819266474334253578972440047168279142184141910485872726393507923996391796227576994885784959692699388957187699662551912804856807879764447982440118185734843107861320087767180763032071844141444498
# FLAG= *******************************
hash_value = '1cd920cc96d95280c96dd519df9ef49fed44c0ccfc80202372d1d196ea52ccb1'
value_r = 55738970979693187681378167695787130117222895714960965190485398883361826593727577547551100491285488657995662094510198245807164881975668033129508588482949937072551764160574163358989597712065236233432502150653495180122562651440328815420270936429340024510654195118602283837975822678425908768515924976212206091388
value_s = 16167384383010337939063062611160328697878797853686180912699394152331808942993583340068941838844464059078517385061012722104618040645796346201205622044690989665622791251498050801728558982153896995503905626972211668853043513769350513237538819164197920332285202321957958655237257294973629465658550364418471213584


A=ZZ(inverse(int(hash_value, 16),prime_q)*value_r %prime_q)
B=ZZ(inverse(int(hash_value, 16),prime_q)*value_s %prime_q)
RR=RationalField(1024)

M=Matrix(RR,3,3)
M[0,0]=prime_q
M[1,0]=-A
M[2,0]=B
M[1,1]=2^(384+512)/2^1024
M[2,2]=2^(512)
M.LLL()

ouput

[69926697342996842887242115923853189774766274334095360573032015342436014501831440985383441433582944809103120272795169946324148984957367 -4675373325063939104739945235827575248496868545626607019126848342129312834075044302850501316166275362512389953001439866250519368074174211293886561786517651216509348739682931/85070591730234615865843651857942052864 0]
[-2569496255658063235601118995298115608880492725906081262130343374668068659687383552778218112682613341296900248310780989355131614412322960 -1135023758615815894126524437513022891668024259751630182806622050992906298140981319621419926380873488776139112853608476249678752133179075267713602818637291365395212559394616633/340282366920938463463374607431768211456 0]
[136143999223146436085508460097629742205 1279477295944917452736163764530539372838401754918551671693014895273072460317224622035796315759721010075556615772779019675040286213110560900266669591412185/85070591730234615865843651857942052864 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096]
long_to_bytes(136143999223146436085508460097629742205)
#b'flag{51b72e34bd}'

高职组

未知题目名字

def Linear_Recurrence(a, b, p1, p0):
    def one_round(p0, p1):
        return vector([a * p0 - b * p1, p0])

    def Iteration(msg):
        Ns = N['p0, p1']
        (p0, p1) = Ns._first_ngens(2)
        if msg == 0: 
            return vector([p0, p1])
        half = Iteration(msg // 2)
        full = half(*half)
        if msg % 2 == 0: 
            return full
        else: 
            return one_round(*full)

    return list(Iteration(msg)(p1, p0))

先看一下关键代码吧。不知道从何讲起。是一个递推的过程。具体的话还是自己推导一两组。

这里就很绕

m s g = 0 b 1 msg=0b1 msg=0b1的情况

先进入

half = Iteration(msg // 2)

然后返回值是

(p0,p1)

进入下一步判断

if msg % 2 == 0: 
            return full
        else: 
            return one_round(*full)

返回

(a*p0-b*p1,p0)

m s g = 0 b 10 msg=0b10 msg=0b10的情况

最终算下来是

(a*(a*p0-b*p1)-b*p0,a*p0-b*p1)

改成矩阵表达
( a − b 1 ) \begin{pmatrix} a& -b\\1\end{pmatrix} (a1b)
后来就变成矩阵的运算了,这块递推还是自己看比较好。我直接说结论。
( a − b 1 ) m s g ∗ ( p 1 p 0 ) = I t e r a t i o n ( m s g ) \begin{pmatrix} a& -b\\1\end{pmatrix} ^{msg}*\begin{pmatrix}p_1\\p_0 \end{pmatrix}=Iteration(msg) (a1b)msg(p1p0)=Iteration(msg)
下面我们的问题就转成矩阵运算的形式了。

题目只给出了 I t e r a t i o n ( m s g ) Iteration(msg) Iteration(msg)的第一位,也就是上面矩阵运算结果的第一位
( a − b 1 ) m s g ∗ ( p 1 p 0 ) = ( A ? ) \begin{pmatrix} a& -b\\1\end{pmatrix} ^{msg}*\begin{pmatrix}p_1\\p_0 \end{pmatrix}=\begin{pmatrix}A\\? \end{pmatrix} (a1b)msg(p1p0)=(A?)
题目给出了四组结果,我把他们放进一个矩阵里面
( a 0 − b 0 1 a 1 b 1 1 a 2 b 2 1 a 3 b 3 1 ) k ∗ ( p 0 ⋮ p 7 ) = ( A ? B ? C ? D ? ) \begin{pmatrix} a_0& -b_0&&&&&&\\1&\\&&a_1&b_1&&&&\\&&1&&&&\\&&&&a_2&b_2&&\\&&&&1&&&\\&&&&&&a_3&b_3\\&&&&&&1\end{pmatrix}^{k}*\begin{pmatrix}p_0\\\vdots\\p_7 \end{pmatrix}=\begin{pmatrix}A\\?\\B\\?\\C\\?\\D\\? \end{pmatrix} a01b0a11b1a21b2a31b3 k p0p7 = A?B?C?D?
其中A,B,C,D为已知值
设最左边的为矩阵 M 设最左边的为矩阵M 设最左边的为矩阵M
对M进行Jordan形式展开
p ∗ N ∗ p − 1 = = M p*N*p^{-1}==M pNp1==M
其中p为变换矩阵,N为Jordan标准型,不知道的话可以搜一下学一学。

A=Matrix([[6,-9],[1,0]])
B=Matrix([[8,-15],[1,0]])
C=Matrix([[10,-21],[1,0]])
D=Matrix([[12,-35],[1,0]])
M=Matrix(Zmod(n),8)
M[:2,:2]=A
M[2:4,2:4]=B
M[4:6,4:6]=C
M[6:8,6:8]=D

pp=[]
for i,j in zip(p1,p0):
    pp.extend([i,j])
P=vector(Zmod(n),pp)
N, p_mat = M.jordan_form(transformation=True)

print('[+] jordan normal for M:')
for i in N:
    print(i)
print()

print(p_mat[0],p_mat[2],p_mat[4],p_mat[6])
p_mat*N*p_mat.inverse()==M
[+] jordan normal for M:
(7, 0, 0, 0, 0, 0, 0, 0)
(0, 7, 0, 0, 0, 0, 0, 0)
(0, 0, 5, 0, 0, 0, 0, 0)
(0, 0, 0, 5, 0, 0, 0, 0)
(0, 0, 0, 0, 3, 1, 0, 0)
(0, 0, 0, 0, 0, 3, 0, 0)
(0, 0, 0, 0, 0, 0, 3, 0)
(0, 0, 0, 0, 0, 0, 0, 3)

(0, 0, 0, 0, 3, 1, 0, 0) (0, 0, 1, 0, 0, 0, 1, 0) (1, 0, 0, 0, 0, 0, 0, 1) (0, 1, 0, 1, 0, 0, 0, 0)
True

p ∗ N k ∗ p − 1 ∗ P = R p*N^{k}*p^{-1}*P=R pNkp1P=R

Jordan矩阵N的k次方为
( 7 k 7 k 5 k 5 k 3 k k ∗ 3 k − 1 3 k 3 k 3 k ) \begin{pmatrix}7^k&&&&&&&\\&7^k&&&&&&\\&&5^k&&&&\\&&&5^k&&&\\ &&&&3^k&k*3^{k-1}&&&\\&&&&&3^k&&\\&&&&&&3^k&\\&&&&&&&3^k\end{pmatrix} 7k7k5k5k3kk3k13k3k3k
这个结论的话设个未知数就出来了

然后对于
X = N k ∗ p − 1 ∗ P L = p − 1 ∗ P X=N^k*p^{-1}*P\\L=p^{-1}*P X=Nkp1PL=p1P
X可以合并成8行1列的向量,其中包含未知数

然后对于结果矩阵R只知道第0,2,4,6次项。所以我只需要取出变换矩阵p的第0,2,4,6行

(0, 0, 0, 0, 3, 1, 0, 0) (0, 0, 1, 0, 0, 0, 1, 0) (1, 0, 0, 0, 0, 0, 0, 1) (0, 1, 0, 1, 0, 0, 0, 0)

所以可以得出四个等式
{ 3 ∗ ( L 4 ∗ 3 k + L 5 ∗ k ∗ 3 k − 1 ) + 1 ∗ L 5 ∗ 3 k = A L 2 ∗ 5 k + L 6 ∗ 3 k = B L 0 ∗ 7 k + L 7 ∗ 3 k = C L 1 ∗ 7 k + L 3 ∗ 5 k = D \left\{ \begin{aligned} 3*(L_4*3^k+L_5*k*3^{k-1})+1*L_5*3^k&=A \\ L_2*5^k+L_6*3^k &=B\\ L_0*7^k+L_7*3^k &=C\\ L_1*7^k+L_3*5^k &=D \end{aligned} \right. 3(L43k+L5k3k1)+1L53kL25k+L63kL07k+L73kL17k+L35k=A=B=C=D
对于后三个等式可以使用方程组的形式求出 3 k 3^k 3k,然后带入到第一个等式中。
( L 6 L 2 L 7 L 0 L 3 L 1 ) ∗ ( 3 k 5 k 7 k ) = ( B C D ) \begin{pmatrix}L_6&L_2&\\L_7&&L_0\\&L_3&L_1 \end{pmatrix}*\begin{pmatrix}3^k\\5^k\\7^k \end{pmatrix}=\begin{pmatrix}B\\C\\D \end{pmatrix} L6L7L2L3L0L1 3k5k7k = BCD

k = ( A − 3 ∗ L 4 ∗ 3 k − L 5 ∗ 3 k ) ∗ ( L 5 ∗ 3 k ) − 1 k=(A-3*L_4*3^k-L_5*3^k)*(L_5*3^k)^{-1} k=(A3L43kL53k)(L53k)1

完整exp

n=11804750425314341166655294609956038824495116221943590894858505947410759351607136441144196903190475378440445092747129737540647561067572663758842764663528623
a=[6, 8, 10, 12]
b=[9, 15, 21, 35]
p1=[17027883529565117987, 13551665172578294059, 18081141142904161561, 13275652618816985233]
p0=[18177295635603276407, 9505549336920753997, 17072082071431584061, 16118933928114157831]
result=[6715126204564078483354097016702154195859560615336978179500784599440726731556460786176876281922114292082298209354294249945666601248273278019142982495548499, 4379561838842115509931384332618722657166452997822099791164364587216285794747780604876884600694225090103483422215182991395962186513067282566687397746631208, 11380336831236011142546980046782778043332687939355967888606834900673350834797688518380957032417484667750078206083786031138224320350566812889985447618141458, 526989697864292158597239327808519596353997593440974938523160676683040397918271560686917364053908467826619196125006111568110489627217548695566322373320619]

A=Matrix([[6,-9],[1,0]])
B=Matrix([[8,-15],[1,0]])
C=Matrix([[10,-21],[1,0]])
D=Matrix([[12,-35],[1,0]])
M=Matrix(Zmod(n),8)
M[:2,:2]=A
M[2:4,2:4]=B
M[4:6,4:6]=C
M[6:8,6:8]=D

pp=[]
for i,j in zip(p1,p0):
    pp.extend([i,j])
P=vector(Zmod(n),pp)
N, p_mat = M.jordan_form(transformation=True)

print('[+] jordan normal for G:')
for i in N:
    print(i)
print()

print(p_mat[0],p_mat[2],p_mat[4],p_mat[6])
p_mat*N*p_mat.inverse()==M
# p_mat.inverse()*P

ll=p_mat.inverse()*P
sol=Matrix(Zmod(n),3)
sol[0,0]=ll[6]
sol[0,1]=ll[2]
sol[1,0]=ll[7]
sol[1,2]=ll[0]
sol[2,1]=ll[3]
sol[2,2]=ll[1]
rt=vector(Zmod(n),result[1:])

x_3=(sol.inverse()*rt)[0]
long_to_bytes(ZZ((result[0]-3*x_3*ll[4]+x_3*ll[5])*inverse(ZZ(x_3*ll[5]),n) %n))

#b'flag{b7a5c586-dda1-4cf8-90b2-e912543e09be}\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x18'


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值