CRYPTO-DSA

参考某位大佬的博客和nss的一些题目,这两天的DSA题目

DSA数字签名 | DexterJie'Blog

[NCTF 2021]dsa

task.py

from Crypto.Util.number import *
from secret import flag
from hashlib import sha256
import os def keygen():
while True:
p = getPrime(522)
q = p//2
if isPrime(q):
break
g = 3
h = long_to_bytes(getPrime(256))
x = int.from_bytes(h*2, "big")
y = pow(g, x, p)
return g, p, q, y, x def sign(h, x):
k = sha256(h.encode().hex().encode()).digest()+sha256(bytes.fromhex(h)+x.to_bytes(128, "big")).digest()
k = int.from_bytes(k, "big")
r = pow(g,k,p)
s = (r*x+int(h,16))*inverse(k,q)%q
return r, s g, p, q, y, x = keygen()
flag = int(flag[5:-1],16)^int(sha256(x.to_bytes(128, "big")).hexdigest(),16)
r, s = sign(hex(flag)[2:], x)
print(q)
print(y)
print(flag)
print(r)
print(s) '''
q=4065074330205980877463463424406813850154275302695361748314870346411329051948044450952905063182483477758495116696164996888846308775044737816809015524088898203
y=7743982251072012463264403932580827621959049035277930304818871889119878506480333248188293037455476433705911511645160292331990658781048396135284434991466243636
flag=19480592192543881131267167328019941277106895469291691207381812905033306766991
r=962433004607153392099715322793248884218264181538005666659905851247468102959956625098831516046715446615198437005036117685792905736788216987378584513020215442
s=1861254747644911591100925843087118347161726578606012243057783788330822542299254180561801871884967022902307837045926190782819951409650425825871898890839825777
'''
\[p=2*q+1
\]
\[x=(2^{256}+1)*d^{'}
\]

据说k是H和H+X的哈希拼接,所以可以知道k的高256位(有没有人能解释的)

\[H=m异或 h(m)\\
\]
\[k=h(H)+h(H+x)=>k=H(2^{256})+h^{'}\\
\]
\[f(x)=(2^{256}H+h^{'})*s-(2^{256+1})*d^{'}*r-H\ (mod\ q)
\]

就是flag的低位和d‘的二元copper

def small_roots(f, bounds, m=1, d=None):
if not d:
d = f.degree() R = f.base_ring()
N = R.cardinality() f /= f.coefficients().pop(0)
f = f.change_ring(ZZ) G = Sequence([], f.parent())
for i in range(m + 1):
base = N ^ (m - i) * f ^ i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g) B, monomials = G.coefficient_matrix()
monomials = vector(monomials) factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor) B = B.dense_matrix().LLL() B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1 / factor) H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B * monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots return [] from Crypto.Util.number import *
from hashlib import sha256
import itertools
q = 4065074330205980877463463424406813850154275302695361748314870346411329051948044450952905063182483477758495116696164996888846308775044737816809015524088898203
y = 7743982251072012463264403932580827621959049035277930304818871889119878506480333248188293037455476433705911511645160292331990658781048396135284434991466243636
h = 19480592192543881131267167328019941277106895469291691207381812905033306766991
r = 962433004607153392099715322793248884218264181538005666659905851247468102959956625098831516046715446615198437005036117685792905736788216987378584513020215442
s = 1861254747644911591100925843087118347161726578606012243057783788330822542299254180561801871884967022902307837045926190782819951409650425825871898890839825777
g = 3
p = q*2+1
#sagemath
kmax=int(sha256(hex(h)[2:].encode().hex().encode()).digest().hex(),16)
PR.<h_0, d_0> = PolynomialRing(Zmod(q))
f = (2^256 * kmax + h_0) * s - (2^256 + 1) * d_0 * r - h
roots = small_roots(f, [2^256, 2^256], d=4, m=4)
#roots
kmin = int(roots[0][0])
k = kmax*2^256+kmin
x_ = int(roots[0][1])
x_0 = (2^256+1)*x_
if pow(g,x_0,p) == y:
flag = h^^int(sha256(int(x_0).to_bytes(128, "big")).hexdigest(),16)
print(hex(flag)[2:])

[HZNUCTF 2023 preliminary]easyDSA

task.py

from hash import *
from sage import *
from secrets import flag
from Crypto.Util.number import *
from gmpy2 import invert def dsa(hmac, _pk, _sk, k):
_p, _q, _g, _y = _pk
x = _sk
r = pow(_g, k, _p) % _q
s = ((hmac + x * r) * invert(k, _q)) % _q
return int(r), int(s) m = int(flag.hex(), 16)
p = getPrime(2048)
q = getPrime(256)
g = getRandomNBitInteger(2048)
y = pow(g, m, p)
pk = (p, q, g, y)
sk = m
hm1 = int(SM3(default_hm1), 16)
hm2 = int(SM3(default_hm2), 16)
nonce = getPrime(64)
xxxx = getPrime(20)
print(f"(r1, s1) = {dsa(hm1, pk, sk, nonce)}")
print(f"(r2, s2) = {dsa(hm1, pk, sk, nonce ** 2 + xxxx)}")
print(f"p = {p}\nq = {q}\ng = {g}\ny = {y}")
# (r1, s1) = (43665657147136977892760835332544097729763754398125679419859037123212964274095, 11372107439153704547599978617809027960018057676066118055075660375442954789009)
# (r2, s2) = (29184887007213204285288676779168140587575609668559831035949650649308618592275, 5011738292572181542092375902756977363590922060964162373234404450451520414798)
# p = 31961141251107494919420190534228520246958409864267239760354623819192809291490262139213317490432416411403367763443527530375117617196123131270496004125231254335150221348901335274505489844222882171272650010562960614279185073793274638651086760235178963210965828168433516820007716846876686795459738332444629111764967204355463398049697867061034126529189537688874999118692225915790053920062142349951686250122300061810240375783724631961234942175580462986265098353263395579346466921241016500821787793395554444982717141449909744838267161237273856377774256250949274635575801148994817767751541256849860886577256992383324866941911
# q = 69375998045163628324086568160767337544901252262545889505892695427466730978301
# g = 23095306638137759877487469277470910487928442296144598697677211337473146684728707820084075779044942034329888686699655576145455963231144004571165817481066424910959951439014314776050521403558035997997820617824839889597136772108383034876458141163933312284054415480674388788905935457149956424898637134087874179010376667509489926236214865373552518669840236207944772752416668193786003948717604980584661094548997197117467440864460714843246250800575997370964173558788145639802963655916833143883799542309432910222224223561677245110195809587171802538978009246887077924173034608600837785506594525481696000424121705524449481831586
# y = 30195133393879069638917191223585579396119430591488890396938821804398771785068454607425044458865556053274470709839502680269466948174813926392729790863065933078609827279352860810689776644132512095691760326095517755483748554008211568781998662554432781285208646921699265866446498342049913829592480268053599307065979016922204438675164034767731708343084371572648019835171087671868322447023378942812010740490724160077164191297435291229504616686997442254543493394641023587237077429236872101951650325361004443988267286616139798736713430746804524113024341440435623834197278500144543476528466395780355874841379098027115073850819

给了3个文件,主要还是看task.py

关系式

\[s1\equiv (H_1+r_1x)k_1^{-1}\\
\]
\[s2\equiv (H_2+r2x)k_2^{-1}
\]

已知

\[k_2=k_1^{2}+x_0\\
\]
\[H_1=H_2\\
\]

构造二元copper

\[f(x)=(s_2(k_1^2+x_0)-H_2)r_2^{-1}-(s_1k_1-H_1)*r^{-1}
\]

SM3可以直接用在线平台算。

exp

(r1, s1) = (43665657147136977892760835332544097729763754398125679419859037123212964274095, 11372107439153704547599978617809027960018057676066118055075660375442954789009)
(r2, s2) = (29184887007213204285288676779168140587575609668559831035949650649308618592275, 5011738292572181542092375902756977363590922060964162373234404450451520414798)
p = 31961141251107494919420190534228520246958409864267239760354623819192809291490262139213317490432416411403367763443527530375117617196123131270496004125231254335150221348901335274505489844222882171272650010562960614279185073793274638651086760235178963210965828168433516820007716846876686795459738332444629111764967204355463398049697867061034126529189537688874999118692225915790053920062142349951686250122300061810240375783724631961234942175580462986265098353263395579346466921241016500821787793395554444982717141449909744838267161237273856377774256250949274635575801148994817767751541256849860886577256992383324866941911
q = 69375998045163628324086568160767337544901252262545889505892695427466730978301
g = 23095306638137759877487469277470910487928442296144598697677211337473146684728707820084075779044942034329888686699655576145455963231144004571165817481066424910959951439014314776050521403558035997997820617824839889597136772108383034876458141163933312284054415480674388788905935457149956424898637134087874179010376667509489926236214865373552518669840236207944772752416668193786003948717604980584661094548997197117467440864460714843246250800575997370964173558788145639802963655916833143883799542309432910222224223561677245110195809587171802538978009246887077924173034608600837785506594525481696000424121705524449481831586
y = 30195133393879069638917191223585579396119430591488890396938821804398771785068454607425044458865556053274470709839502680269466948174813926392729790863065933078609827279352860810689776644132512095691760326095517755483748554008211568781998662554432781285208646921699265866446498342049913829592480268053599307065979016922204438675164034767731708343084371572648019835171087671868322447023378942812010740490724160077164191297435291229504616686997442254543493394641023587237077429236872101951650325361004443988267286616139798736713430746804524113024341440435623834197278500144543476528466395780355874841379098027115073850819
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Crypto.Util.number import*
import itertools
IV = 0x7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e
default_hm1 = b'HZNUCTFRound#1'
default_hm2 = b'HZNUCTFRound#1' def small_roots(f, bounds, m=1, d=None):
if not d:
d = f.degree() R = f.base_ring()
N = R.cardinality() f /= f.coefficients().pop(0)
f = f.change_ring(ZZ) G = Sequence([], f.parent())
for i in range(m + 1):
base = N ^ (m - i) * f ^ i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g) B, monomials = G.coefficient_matrix()
monomials = vector(monomials) factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor) B = B.dense_matrix().LLL() B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1 / factor) H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B * monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots return []
H1=19905280947443115569469777697852124038269468456842113763109865796452965095134
H2=H1
PR.<k1, x0> = PolynomialRing(Zmod(q))
f = (s2*(k1**2+x0)-H2)*inverse(r2,q)-(s1*k1-H1)*inverse(r1,q)
roots = small_roots(f, (2^64, 2^20), m=1, d=2)
print(roots)
k1,x0=roots[0]
#[(15744441039285451081, 631339)]
k2=k1**2+x0
x = (s1*k1-H1)*inverse(r1,q)%q
print(long_to_bytes(int(x))

[suctf 2019]DSA

在终端里面交互

得到DSA的参数。发现有几组的r相同,于是可以构造方程组求私钥x,把私钥求出来后,将终端给你的签名消息的hash值进行签名,将会得道签名对(r,s),将签名对与终端交互,得到flag

\[k*s1 = H(m1) + x*r\ mod\ q\\
\]
\[k*s2 = H(m2) + x*r\ mod\ q
\]

exp

import gmpy2

r =645224390501315862797070591755816309562736584452
h_flag = 334436397493699539473999398012751306876
p=89884656743115797097819440555693178620485594490643767510103963471608924587913709653256746790562883588011852460735275267990503465149454718627614453763060059226676569508565322541877120147735776580975577455382906808621021450526077323235477260260610074352985347306411700160496668007768862436197980651598048994217 q=733351900012832584621865112243949059368957476097 g=88493223492302907020961042092534061870813103426197667060896649536511822654652196955971640083365037379740401608129629097454817124374624947279386614844301750312126039698542869587208495662827992222619770171959869103091417006779702356792342825516705379752141737800147265145023116961039150128411592713662148401589 y=52169245435909876495152421578533821340872117742587260268454403838425273037980176268874598797032049946042829131912183461753205871292554332715861109864480014054314530798154726283889479994795350311013632333809929713875409593432791157873854766290466911161859680981529617530940854956585734363116431329106262579369
h1 = 193111848988193367504523557345609960681
h2 = 6552181908429515529989854270507740427
s1 = 624451987004675139546639048435927733971094708317
s2 = 206502049020604103620526858798020639447000006522
ds = s2-s1
dh = h2-h1
k = gmpy2.mul(dh,gmpy2.invert(ds,q))
k = gmpy2.f_mod(k,q)
tmp = gmpy2.mul(k,s1)-h1
x = tmp*gmpy2.invert(r,q)
x = gmpy2.f_mod(x,q)
print(int(x))
s_flag = (gmpy2.invert(k,q)*(h_flag+x*r)) % q
print((r,s_flag))
#(645224390501315862797070591755816309562736584452L, 497133993307905006634015243473843926347603500982L)

[D^3CTF 2022]leak_dsa

task.py

from hashlib import sha256
from secret import flag
from Crypto.Util.number import *
from random import *
import os
from binascii import *
def gen_key(qbit , pbit):
q = getPrime(qbit)
while 1:
p = getrandbits(pbit-qbit)*q + 1
if isPrime(p):
break
while 1:
h = randint(1 , p)
g = pow(h , (p-1)//q , p)
if g != 1:
break
d = randint(1 , q-1)
y = pow(g,d,p)
pubkey = (p ,q , g ,y)
prikey = (p ,q ,g ,y , d)
return pubkey , prikey
def sign(prikey , m):
p,q,g,y,d = prikey
k = randint(1 , q-1)
r = pow(g , k , p) % q
s = inverse(k , q) * (int(sha256(m).hexdigest(),16)+ d * r) % q
return (r , s) , k
def verify(pubkey , m , r ,s ):
p,q,g,y = pubkey
w = inverse(s , q)
u1 = int(sha256(m).hexdigest(),16) * w % q
u2 = r * w % q
if r == pow(g , u1 , p)*pow(y , u2,p)% q:
return 1
return 0
N = 70
pubkey , prikey = gen_key(256 , 2048)
f = open('./cipher.txt' , 'w')
f.write(str(pubkey) + '\n')
for i in range(N):
m = os.urandom(10)
signature , gift = sign(prikey , m)
mask = getrandbits(256)
f.write(hexlify(m).decode() + ',' + str(signature) +',' +str(mask & gift) +','+ str(mask) + '\n')
assert flag[:6] == b'd3ctf{' and flag[-1:] == b'}'
assert flag[6:-1] == sha256(str(prikey[-1]).encode()).hexdigest()

给个链接吧:D^3CTF 2022 - hash_hash - 博客园是一种基于DSA的HNP问题

基于DSA的HNP问题

DSA数字签名 | DexterJie'Blog

\[A=s^{-1}\ mod\ q\\
\]
\[B=s^{-1}H\ mod\ q
\]

所以

\[k\equiv Ax+B\ mod\ q
\]

\[(t_1 \quad t_2 \quad \ldots \quad t_n \quad x \quad 1)
\begin{pmatrix}
q & 0 & \ldots & 0 & 0 & 0 \\
0 & q & \ldots & 0 & 0 & 0 \\
\vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\
0 & 0 & \ldots & q & 0 & 0 \\
A_1 & A_2 & \ldots & A_n & 1 & 0 \\
B_1 & B_2 & \ldots & B_n & 0 & K
\end{pmatrix}
= (k_1 \quad k_2 \quad \ldots \quad k_n \quad x \quad K)
\]

当然这是在x不太大的情况下

task.py

from Crypto.Util.number import *
from Crypto.PublicKey import DSA
import random
import hashlib def gen_key():
pri = getPrime(128)
pub = pow(g,pri,p)
return pri,pub def sign(m,pri):
k = getPrime(128)
H = int(hashlib.sha256(m).hexdigest(),16)
r = pow(g,k,p) % q
s = pow(k,-1,q) * (H + pri * r) % q
return r,s key = DSA.generate(1024)
p, q, g = key.p, key.q, key.g
pri, pub = gen_key()
print(f"p = {p}")
print(f"q = {q}")
print(f"g = {g}")
print(f"pub = {pub}") flag = "flag{" + hashlib.sha256(str(pri).encode()).hexdigest() + "}" for i in range(5):
r,s = sign(str(i).encode(),pri)
print(f"r = {r}")
print(f"s = {s}") """
p =
q =
g =
pub =
r =
s =
r =
s =
r =
s =
r =
s =
r =
s =
"""

这有五组签名对

import hashlib
from Crypto.Util.number import * p =
q =
g =
pub = R = [,,,,]
S = [,,,,]
H = [int(hashlib.sha256(str(i).encode()).hexdigest(),16) for i in range(5)] A = [inverse(S[i],q) * R[i] % q for i in range(5)]
B = [inverse(S[i],q) * H[i] % q for i in range(5)]
n = len(A)
K = 2^128 Ge = Matrix(ZZ,n+2,n+2)
for i in range(n):
Ge[i,i] = q
Ge[-2,i] = A[i]
Ge[-1,i] = B[i] Ge[-2,-2] = 1
Ge[-1,-1] = K for line in Ge.LLL():
if line[-1] == K:
x = line[-2]
print(f"x = {x}")
flag = "flag{" + hashlib.sha256(str(x).encode()).hexdigest() + "}"
print(flag)

消元x

当x数量级比较大的时候

\[s_i\equiv k_i^{-1}(H_i+xr_i)\ mod\ q\\
\]
\[k_is_i\equiv H_i+xr_i\ mod\ q
\]

取另外一组签名消去x得到

\[k_is_ir_j\equiv H_rr_j+xr_ir_j\ mod\ q\\
\]
\[k_js_jr_i\equiv H_jr_i+xr_jr_i\ mod\ q
\]

相减得

\[s_ir_jk_i-s_jr_ik_j\equiv H_ir_j-H_jr_i\ mod\ q
\]

取j=0

\[(s_ir_0)k_i-(s_0r_i)k_0\equiv H_ir_0-H_0r_i\ mod\ q
\]

乘以\((r_0s_i)^{-1}\)得到

\[k_i-(r_0s_i)^{-1}(s_0r_i)k_0\equiv (r_0s_i)^{-1}(H_ir_0-H_0r_i)\ mod\ q
\]
\[k_i\equiv A_ik_0+B_i\ mod\ q
\]

有点像LCG的HNP

\[(t_1 \quad t_2 \quad \ldots \quad t_n \quad k_0\quad 1)
\begin{pmatrix}
q & 0 & \ldots & 0 & 0 & 0 \\
0 & q & \ldots & 0 & 0 & 0 \\
\vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\
0 & 0 & \ldots & q & 0 & 0 \\
A_1 & A_2 & \ldots & A_n & 1 & 0 \\
B_1 & B_2 & \ldots & B_n & 0 & K
\end{pmatrix}
= (k_1 \quad k_2 \quad \ldots \quad k_n \quad k_0 \quad K)
\]

春秋杯——signature

task.py

import os
import hashlib
from Crypto.Util.number import *
from Crypto.PublicKey import DSA
import random
def gen_proof_key():
password = 'happy_the_year_of_loong'
getin = ''
for i in password:
if random.randint(0, 1):
getin += i.lower()
else:
getin += i.upper()
ans = hashlib.sha256(getin.encode()).hexdigest()
return getin,ans def gen_key():
pri = random.randint(2,q - 2)
pub = pow(g,pri,p)
return pri,pub def sign(m,pri):
k = int(hashlib.md5(os.urandom(20)).hexdigest(),16)
H = int(hashlib.sha256(m).hexdigest(),16)
r = pow(g,k,p) % q
s = pow(k,-1,q) * (H + pri * r) % q
return r,s def verify(pub,m,signature):
r,s = signature
if r <= 0 or r >= q or s <= 0 or s >= q:
return False
w = pow(s,-1,q)
H = int(hashlib.sha256(m).hexdigest(),16)
u1 = H * w % q
u2 = r * w % q
v = (pow(g,u1,p) * pow(pub,u2,p) % p) % q
return v == r def login():
print('Hello sir,Plz login first')
menu = '''
1.sign
2.verify
3.get my key
'''
times = 8
while True:
print(menu)
if times < 0:
print('Timeout!')
return False
choice = int(input('>'))
if choice == 1:
name = input('Username:').encode()
if b'admin' in name:
print('Get out!')
return False
r,s = sign(name,pri)
print(f'This is your signature -- > {r},{s}')
times -= 1
elif choice == 2:
print('Sure,Plz input your signature')
print(pri)
r = int(input('r:'))
s = int(input('s:'))
if verify(pub,b'admin',(r,s)) == True:
print('login success!')
return True
else:
print('you are not admin')
return False
elif choice == 3:
print(f'Oh,your key is {(p,q,g)}')
getin,ans = gen_proof_key()
print(f'Your gift --> {ans[:6]}')
your_token = input('Plz input your token\n>')
if your_token != getin:
print('Get out!')
exit(0) key = DSA.generate(1024)
p, q, g = key.p, key.q, key.g
pri, pub = gen_key()
if login() == False:
exit(0)
print(open('/flag','r').read())

开始就是一段字符串的大小写混淆,它给了我们hash值,于是我们暴破,直到hash值一样。

接着就是得到DSA的参数p,q,g,我们有8次获得签名对的机会。

然后利用这8组造格

import hashlib
import itertools
from tqdm import *
from pwn import *
from Crypto.Util.number import * def pass_proof(head):
password = 'happytheyearofloong'
table = itertools.product([0,1],repeat=19)
for i in tqdm(table):
getin = ""
for j in range(len(i)):
if i[j] == 0:
getin += password[j].lower()
else:
getin += password[j].upper()
msg = getin[:5] + "_" + getin[5:8] + "_" + getin[8:12] + "_" + getin[12:14] + "_" + getin[14:]
h = hashlib.sha256(msg.encode()).hexdigest()
if h[:6] == head:
print(msg)
return msg sh = remote("8.147.132.12",41792)
head = sh.recvline().strip().decode().split(" ")[-1]
msg = pass_proof(head)
sh.recvuntil(b"Plz input your token")
sh.sendlineafter(b">",msg.encode())
sh.recvuntil(b"3.get my key\n")
sh.sendlineafter(b">",b"3")
(p,q,g) = eval(sh.recvline().strip().decode().split("Oh,your key is ")[-1]) H = []
R = []
S = [] for i in range(8):
name = b"a"*(i+1)
sh.recvuntil(b"3.get my key\n")
sh.sendlineafter(b">",b"1")
sh.sendlineafter(b"Username:",name)
data = sh.recvline().strip().decode()
print(data)
r = int(data.split(" ")[-1].split(',')[0])
s = int(data.split(" ")[-1].split(',')[1])
h = int(hashlib.sha256(name).hexdigest(),16)
R.append(r)
S.append(s)
H.append(h) def get_k():
n = len(R)
r0 = R[0]
h0 = H[0]
s0 = S[0]
A = []
B = [] for i in range(n):
a = inverse((r0 * S[i]),q) * (R[i] * s0) % q
b = inverse((r0 * S[i]),q) * (H[i]*r0 - h0 * R[i])
A.append(a)
B.append(b) Ge = Matrix(ZZ,n+2,n+2)
for i in range(n):
Ge[i,i] = q
Ge[-2,i] = A[i]
Ge[-1,i] = B[i]
K = 2**128
Ge[-2,-2] = 1
Ge[-1,-1] = K for line in Ge.LLL():
if abs(line[-1]) == K:
return line[-2] k0 = get_k()
print(f"k0 = {k0}")
sh.recvuntil(b"3.get my key\n")
sh.sendlineafter(b">",b"2")
sh.recvline()
x = int(sh.recvline().strip().decode())
r = pow(g,k0,p) % q
hh = int(hashlib.sha256(b"admin").hexdigest(),16)
s = pow(k0,-1,q) * (hh + x*r) % q
sh.sendlineafter(b"r:",str(r).encode())
sh.sendlineafter(b"s:",str(s).encode())
print(sh.recvline().strip().decode())
print(sh.recvline().strip().decode())

给出k的高位

k写成\(k=2^hk_h+k_{un}2^l+k_l\)

一系列化简得到,\(A_i\equiv (s_ir_02^l)^{-1}(s_0r_i2^l)k_{0un}\ mod\ q\)

\(B_i\equiv (s_ir_02^l)^{-1}(H_ir_0-H_0r_i+(s_0r_i)(k_{0h}2^h+k_{0l})-(s_ir_0)(k_{ih}2^h+k_{il}))\ mod\ q\)

\[k_{iun}\equiv A_ik_{0un}+B_i\ mod\ q
\]
\[(t_1 \quad t_2 \quad \ldots \quad t_n \quad k_{0un}\quad 1)
\begin{pmatrix}
q & 0 & \ldots & 0 & 0 & 0 \\
0 & q & \ldots & 0 & 0 & 0 \\
\vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\
0 & 0 & \ldots & q & 0 & 0 \\
A_1 & A_2 & \ldots & A_n & 1 & 0 \\
B_1 & B_2 & \ldots & B_n & 0 & K
\end{pmatrix}
= (k_{1un} \quad k_{2un} \quad \ldots \quad k_{nun} \quad k_{0un} \quad K)
\]

2024RCTF——SignSystem

task.py

from random import getrandbits, randint
from Crypto.Util.number import getPrime, isPrime, inverse
from hashlib import sha1
import signal def gen(l, n):
q = getPrime(l)
while True:
t = getrandbits(n - l)
p = t * q + 1
if isPrime(p):
break
h = randint(1, p - 1)
g = pow(h, t, p)
x = randint(1, q)
y = pow(g, x, p)
return (p, q, g, y), x def gen_ephemeral_key(k, lsb, msb):
return msb << (k + lsb.bit_length()) | getrandbits(k) << lsb.bit_length() | lsb def sign(pubkey, x, msg, lsb, msb):
p, q, g, y = pubkey
k = gen_ephemeral_key(150, lsb, msb)
r = pow(g, k, p) % q
Hm = int(sha1(msg).hexdigest(), 16)
s = (Hm + x * r) * inverse(k, q) % q
return (r, s) def verify(pubkey, sig, msg):
p, q, g, y = pubkey
r, s = sig
if not 0 < r < q or not 0 < s < q:
return False
w = inverse(s, q)
Hm = int(sha1(msg).hexdigest(), 16)
u1 = Hm * w % q
u2 = r * w % q
v = pow(g, u1, p) * pow(y, u2, p) % p % q
return v == r signal.alarm(900)
with open("flag.txt", "r") as f:
flag = f.read() l, n = 160, 1024
pub, x = gen(l, n)
print("your pubKey: {}".format(pub))
msb = getrandbits(8)
lsb = getrandbits(2) menu = """
[1] sign message
[2] verify signature
""" for i in range(20):
print(menu)
op = int(input(">").strip())
if op == 1:
msg = input("Which message to sign?: ").strip().encode()
if msg == b"get flag":
print("I'm afraid I can't do that.")
break
else:
sig = sign(pub, x, msg, lsb, msb)
print(f"Signature: {sig}")
elif op == 2:
msg = input("Which message to verify?: ").strip().encode()
r = int(input("r:").strip())
s = int(input("s:").strip())
v = verify(pub, (r, s), msg)
if v and msg == b"get flag":
print(flag)
else:
print(v)
else:
print("Invalid option")

可以知道,每个k的高8位和低2位是一样的。

exp

from Crypto.Util.number import *
import string
from pwn import *
from sage.all import *
from tqdm import *
import gmpy2
import time table = string.ascii_lowercase
host = '' #ip地址
port = #端口
sh = remote(host,port) #建立连接
sh.recvuntil(b"your pubKey:")
pub = eval(sh.recvline().decode().strip())
p,q,g,y = pub
R=[]
H=[]
S=[]
for i in range(19):
sh.recvuntil(b">")
sh.sendline(b"1")
sh.recvuntil(b"Which message to sign?:")
m="".join(choices(table,k=16))
msg=m.encode()
sh.sendline(msg)
sh.recvuntil(b"Signature:")
data1=eval(sh.recvline().decode().strip())
r,s=data1
S.append(s)
R.append(r)
H.append(h)
r0=R[0]
s0=S[0]
h0=H[0]
def sign(pubkey, x, msg, lsb, msb):
p, q, g, y = pubkey
k = gen_ephemeral_key(150, lsb, msb)
r = pow(g, k, p) % q
Hm = int(sha1(msg).hexdigest(), 16)
s = (Hm + x * r) * inverse(k, q) % q
return (r, s)
for high in trange(256):
for low in range(4):
lowbit=low.bit_length()
A=[]
B=[]
tt=2**lowbit
for i in range(1,len(R)):
a=s0*R[i]*tt*gmpy2.invert(tt*t0*S[i],q)%q
b=gmpy2.invert(S[i]*r0*2**lowbit,q)*(H[i]*r0-h0*R[i]+(s0*R[i])*(high*2**512+low)-r0*S[i]*(high*2*2**512+low))%q
A.append(a)
B.append(b)
n=len(A) Ge=Matrix(ZZ,n+2,n+2)
for i in range(n):
Ge[i,i]=q
Ge[-2,i]=A[i]
Ge[-1,i]=B[i]
K=2**150
Ge[-2,-2]=1
Ge=[-1,-1]=K
for line in Ge.BKZ(block_size=30):
if abs(line[-1])==K:
k0_unknown=line[-2]
k0 = high*2**152 + k0_unknown*tt + low
d = (k0 * s0 - h0) * gmpy2.invert(r0,q) % q
if pow(g,d,p) == y:
print(1)
sig = sign(pub,d,b"get flag",k0)
r,s = sig
sh.recvuntil(b">")
sh.sendline(b"2")
sh.recvuntil(b"Which message to verify?: ")
sh.sendlineafter(b"r:",str(r).encode())
sh.sendlineafter(b"s:",str(s).encode())
print(sh.recvline())

CRYPTO-DSA的更多相关文章

  1. 2015GitWebRTC编译实录13

    2015.07.21 libboringssl.a 编译通过主要是生成路径,去除test文件比较啰嗦,后继测试需要重点跟进下 CC obj/third_party/boringssl/boringss ...

  2. openssl知识点总结

    openssl知识点总结 实践总结见之前博客:http://www.cnblogs.com/Jclemo/p/6091201.html 简介 openssl是一个功能丰富且自包含的开源安全工具箱.它提 ...

  3. Postman接口自动化测试实例用到的完整的SM2前端加密算法代码

    var __g__ = {}; !function(t,e){"object"==typeof exports?module.exports=exports=e():"f ...

  4. Openssl源代码整理学习---含P7/P10/P12说明

    声明:建议结合Openssl源代码学习: 一.基础知识 1.Openssl 简史 OpenSSL项目是加拿大人Eric A.Yang 和Tim J.Hudson开发,现在有Openssl项目小组负责改 ...

  5. Openssl编程--源码分析

    Openssl编程 赵春平 著 Email: forxy@126.com 第一章 基础知识 8 1.1 对称算法 8 1.2 摘要算法 9 1.3 公钥算法 9 1.4 回调函数 11 第二章 ope ...

  6. Openssl源代码整理学习

    一.基础知识 1.Openssl 简史 OpenSSL项目是加拿大人Eric A.Yang 和Tim J.Hudson开发,现在有Openssl项目小组负责改进和维护:他们是全球一些技术精湛的志愿技术 ...

  7. 基于redis 3.x搭建集群环境

    由于我团队开发的在线坐席系统,即将面对线上每周3000W的下行投放客户,产品的咨询量可能会很大,基于前期,200W的投放时,前10分钟,大概800问题量,平均一个客户大概8个问题,也就是说每分钟10个 ...

  8. nginx 安装手记

    Nginx需要依赖下面3个包 1. gzip 模块需要 zlib 库 ( 下载: http://www.zlib.net/ )  zlib-1.2.8.tar.gz 2. rewrite 模块需要 p ...

  9. openssl源码目录结构

    openssl源代码主要由eay库.ssl库.工具源码.范例源码以及测试源码组成. eay库是基础的库函数,提供了很多功能.源代码放在crypto目录下.包括如下内容: 1) asn.1 DER编码解 ...

  10. OpenSSL源码简介

    1.X.509标准 x509是由国际电信联盟(ITU-T)制定的数字证书标准:包含公钥和用户标志符.CA等: x509是数字证书的规范,P7和P12是两种封装形式:X.509是常见通用的证书格式.所有 ...

随机推荐

  1. csrf跨站请求伪造与校验策略

    目录 一.csrf跨站请求伪造 概念引入 概念讲解 二.csrf校验策略 概念讲解 form表单操作csrf策略 ajax请求csrf策略 三.csrf相关装饰器 一.csrf跨站请求伪造 概念引入 ...

  2. 禅道bug增加自定义字段

    禅道版本 18.9 需求 给禅道的bug模块,增加自定义字段. 目前主要增加"发现阶段"."所属环境"."出现频率" 增加bug的类型 在b ...

  3. arch 音频处显示没有输入或输出设备

    我的设备是 Dell G15 5511, 属于比较新的设备, 查看了 Fourm 与 wiki 后使用 1 yay -S sof-firmware   安装框架之后重启即可使用.

  4. Mysql数据库连接失败SSLException: Unsupported record version Unknown-0.0

    问题描述:mysql版本:5.7.27jdk版本:1.8.0_201 tomcat日志中报错,显示连接数据库失败,报错信息如下: The last packet successfully receiv ...

  5. Mac下如何添加User到group中

    原因: 使用mac的时候需要像linux一样对用户和群组进行操作,但是linux使用的gpasswd和usermod在mac上都不可以使用,mac使用dscl来对group和user操作. 介绍: $ ...

  6. Qt音视频开发45-视频传输TCP版

    一.前言 做音视频开发,会遇到将音视频重新转发出去的需求,当然终极大法是推流转发,还有一些简单的场景是直接自定义协议将视频传出去就行,局域网的话速度还是不错的.很多年前就做过类似的项目,无非就是将本地 ...

  7. SpringBoot原理深入及源码剖析(二) 自定义Starter及SpringBoot执行原理

    自定义Starter SpringBoot starter机制 SpringBoot由众多starter组成(一系列的自动化配置的starter插件),SpringBoot之所以流行,也是因为star ...

  8. .net core反射练习-简易版IOC容器实现

    实现一个简易的IOC容器 先说一下简单思路,参考ServiceCollection,需要一个注册方法跟获取实例方法,同时支持构造函数注入.那么只需要一个地方存储注册接口跟该接口的继承类,以及根据类的构 ...

  9. [LC814]二叉树剪枝

    题目 题目地址 分析 这道题符合递归的性质,对于当前的节点node,当且仅当其左右孩子都为不包含1的子树,且node.val=1时,node所在的子树才符合"不包含1的子树"这一定 ...

  10. c# 更改快捷方式文件图标

    c# 更改快捷方式文件图标c# 更改快捷方式文件图标c# 更改快捷方式文件图标c# 更改快捷方式文件图标c# 更改快捷方式文件图标c# 更改快捷方式文件图标c# 更改快捷方式文件图标c# 更改快捷方式 ...