文章目录
- 青龙组
- Crypto1
- Crypto2
 
- 白虎组
- Crypto1
- Crypto2
 
- 朱雀组
- Crypto2
- Crypto3
- part1
- part2
- part3
- part4
 
 
 
 
青龙组
Crypto1
题目:
from Crypto.Util.number import *
from secret import flag
p = getPrime(512)
q = getPrime(512)
n = p * q
d = getPrime(299)
e = inverse(d,(p-1)*(q-1))
m = bytes_to_long(flag)
c = pow(m,e,n)
hint1 = p >> (512-70)
hint2 = q >> (512-70)
print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")
print(f"hint1 = {hint1}")
print(f"hint2 = {hint2}")
n = 123789043095302886784777548580725867919630872720308267296330863659260260632444171595208750648710642616709290340791408935502415290984231140635423328808872594955139658822363033096014857287439409252367248420356169878044065798634016290690979979625051287064109800759113475629317869327100941592970373827299442569489
e = 112070481298571389221611833986644006256566240788306316765530852688390558290807060037831460397016038678699757261874520899143918664293504728402666398893964929840011110057060969775245481057773655679041350091817099143204028098431544760662690479779286160425059494739419234859710815966582837874194763305328789592245
c = 63662561509209168743977531923281040338804656992093161358503738280395090747786427812762995865224617853709000826994250614233562094619845247321880231488631212423212167167713869682181551433686816142488666533035193128298379649809096863305651271646535125466745409868274019550361728139482502448613835444108383177119
hint1 = 897446442156802074692
hint2 = 1069442646630079275131
论文:367.pdf
 
高位boneh_durfee攻击
 exp:
import time
time.clock = time.time
 
debug = True
 
strict = False
 
helpful_only = True
dimension_min = 7 # 如果晶格达到该尺寸,则停止移除
# 显示有用矢量的统计数据
def helpful_vectors(BB, modulus):
    nothelpful = 0
    for ii in range(BB.dimensions()[0]):
        if BB[ii,ii] >= modulus:
            nothelpful += 1
# 显示带有 0 和 X 的矩阵
def matrix_overview(BB, bound):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d ' % ii)
        for jj in range(BB.dimensions()[1]):
            a += '0' if BB[ii,jj] == 0 else 'X'
            if BB.dimensions()[0] < 60: 
                a += ' '
        if BB[ii, ii] >= bound:
            a += '~'
        #print (a)
# 尝试删除无用的向量
# 从当前 = n-1(最后一个向量)开始
def remove_unhelpful(BB, monomials, bound, current):
    # 我们从当前 = n-1(最后一个向量)开始
    if current == -1 or BB.dimensions()[0] <= dimension_min:
        return BB
 
    # 开始从后面检查
    for ii in range(current, -1, -1):
        #  如果它没有用
        if BB[ii, ii] >= bound:
            affected_vectors = 0
            affected_vector_index = 0
             # 让我们检查它是否影响其他向量
            for jj in range(ii + 1, BB.dimensions()[0]):
                # 如果另一个向量受到影响:
                # 我们增加计数
                if BB[jj, ii] != 0:
                    affected_vectors += 1
                    affected_vector_index = jj
 
            # 等级:0
            # 如果没有其他载体最终受到影响
            # 我们删除它
            if affected_vectors == 0:
                #print ("* removing unhelpful vector", ii)
                BB = BB.delete_columns([ii])
                BB = BB.delete_rows([ii])
                monomials.pop(ii)
                BB = remove_unhelpful(BB, monomials, bound, ii-1)
                return BB
 
           # 等级:1
            #如果只有一个受到影响,我们会检查
            # 如果它正在影响别的向量
            elif affected_vectors == 1:
                affected_deeper = True
                for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
                    # 如果它影响哪怕一个向量
                    # 我们放弃这个
                    if BB[kk, affected_vector_index] != 0:
                        affected_deeper = False
                # 如果没有其他向量受到影响,则将其删除,并且
                # 这个有用的向量不够有用
                #与我们无用的相比
                if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
                    #print ("* removing unhelpful vectors", ii, "and", affected_vector_index)
                    BB = BB.delete_columns([affected_vector_index, ii])
                    BB = BB.delete_rows([affected_vector_index, ii])
                    monomials.pop(affected_vector_index)
                    monomials.pop(ii)
                    BB = remove_unhelpful(BB, monomials, bound, ii-1)
                    return BB
    # nothing happened
    return BB
 
""" 
Returns:
* 0,0   if it fails
* -1,-1 如果 "strict=true",并且行列式不受约束
* x0,y0 the solutions of `pol`
"""
def boneh_durfee(pol, modulus, mm, tt, XX, YY):
    """
    Boneh and Durfee revisited by Herrmann and May
 
 在以下情况下找到解决方案:
* d < N^delta
* |x|< e^delta
* |y|< e^0.5
每当 delta < 1 - sqrt(2)/2 ~ 0.292
    """
 
    # substitution (Herrman and May)
    PR.<u, x, y> = PolynomialRing(ZZ)   #多项式环
    Q = PR.quotient(x*y + 1 - u)        #  u = xy + 1
    polZ = Q(pol).lift()
 
    UU = XX*YY + 1
 
    # x-移位
    gg = []
    for kk in range(mm + 1):
        for ii in range(mm - kk + 1):
            xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk
            gg.append(xshift)
    gg.sort()
 
    # 单项式 x 移位列表
    monomials = []
    for polynomial in gg:
        for monomial in polynomial.monomials(): #对于多项式中的单项式。单项式():
            if monomial not in monomials:  # 如果单项不在单项中
                monomials.append(monomial)
    monomials.sort()
 
    # y-移位
    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk)
            yshift = Q(yshift).lift()
            gg.append(yshift) # substitution
 
    # 单项式 y 移位列表
    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            monomials.append(u^kk * y^jj)
 
    # 构造格 B
    nn = len(monomials)
    BB = Matrix(ZZ, nn)
    for ii in range(nn):
        BB[ii, 0] = gg[ii](0, 0, 0)
        for jj in range(1, ii + 1):
            if monomials[jj] in gg[ii].monomials():
                BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)
 
    #约化格的原型
    if helpful_only:
        #  #自动删除
        BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1)
        # 重置维度
        nn = BB.dimensions()[0]
        if nn == 0:
            print ("failure")
            return 0,0
 
    # 检查向量是否有帮助
    if debug:
        helpful_vectors(BB, modulus^mm)
 
    # 检查行列式是否正确界定
    det = BB.det()
    bound = modulus^(mm*nn)
    if det >= bound:
        print ("We do not have det < bound. Solutions might not be found.")
        print ("Try with highers m and t.")
        if debug:
            diff = (log(det) - log(bound)) / log(2)
            print ("size det(L) - size e^(m*n) = ", floor(diff))
        if strict:
            return -1, -1
    else:
        print ("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")
 
    # display the lattice basis
    if debug:
        matrix_overview(BB, modulus^mm)
 
    # LLL
    if debug:
        print ("optimizing basis of the lattice via LLL, this can take a long time")
 
    #BB = BB.BKZ(block_size=25)
    BB = BB.LLL()
 
    if debug:
        print ("LLL is done!")
 
    # 替换向量 i 和 j ->多项式 1 和 2
    if debug:
        print ("在格中寻找线性无关向量")
    found_polynomials = False
 
    for pol1_idx in range(nn - 1):
        for pol2_idx in range(pol1_idx + 1, nn):
 
            # 对于i and j, 构造两个多项式
 
            PR.<w,z> = PolynomialRing(ZZ)
            pol1 = pol2 = 0
            for jj in range(nn):
                pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY)
                pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)
 
            # 结果
            PR.<q> = PolynomialRing(ZZ)
            rr = pol1.resultant(pol2)
 
 
            if rr.is_zero() or rr.monomials() == [1]:
                continue
            else:
                print ("found them, using vectors", pol1_idx, "and", pol2_idx)
                found_polynomials = True
                break
        if found_polynomials:
            break
 
    if not found_polynomials:
        print ("no independant vectors could be found. This should very rarely happen...")
        return 0, 0
 
    rr = rr(q, q)
 
    # solutions
    soly = rr.roots()
 
    if len(soly) == 0:
        print ("Your prediction (delta) is too small")
        return 0, 0
 
    soly = soly[0][0]
    ss = pol1(q, soly)
    solx = ss.roots()[0][0]
    return solx, soly
 
def example():
    ############################################
    # 随机生成数据
    ##########################################
    #start_time =time.perf_counter
    start =time.clock()
    size=512
    length_N = 2*size;
    ss=0
    s=70;
    M=1   # the number of experiments
    delta = 299/1024
    # p =  random_prime(2^512,2^511)
    for i in range(M):
#         p =  random_prime(2^size,None,2^(size-1))
#         q =  random_prime(2^size,None,2^(size-1))
#         if(p<q):
#             temp=p
#             p=q
#             q=temp
        N = 123789043095302886784777548580725867919630872720308267296330863659260260632444171595208750648710642616709290340791408935502415290984231140635423328808872594955139658822363033096014857287439409252367248420356169878044065798634016290690979979625051287064109800759113475629317869327100941592970373827299442569489
        e = 112070481298571389221611833986644006256566240788306316765530852688390558290807060037831460397016038678699757261874520899143918664293504728402666398893964929840011110057060969775245481057773655679041350091817099143204028098431544760662690479779286160425059494739419234859710815966582837874194763305328789592245
        c = 63662561509209168743977531923281040338804656992093161358503738280395090747786427812762995865224617853709000826994250614233562094619845247321880231488631212423212167167713869682181551433686816142488666533035193128298379649809096863305651271646535125466745409868274019550361728139482502448613835444108383177119
        hint1 = 897446442156802074692  # p高位
        hint2 = 1069442646630079275131  # q高位
#         print ("p真实高",s,"比特:", int(p/2^(512-s)))
#         print ("q真实高",s,"比特:", int(q/2^(512-s)))
 
#         N = p*q;
 
 
    # 解密指数d的指数( 最大0.292)
 
 
 
        m = 7   # 格大小(越大越好/越慢)
        t = round(((1-2*delta) * m))  # 来自 Herrmann 和 May 的优化
        X = floor(N^delta)  # 
        Y = floor(N^(1/2)/2^s)    # 如果 p、 q 大小相同,则正确
        for l in range(int(hint1),int(hint1)+1):
            print('\n\n\n l=',l)
            pM=l;
            p0=pM*2^(size-s)+2^(size-s)-1;
            q0=N/p0;
            qM=int(q0/2^(size-s))
            A = N + 1-pM*2^(size-s)-qM*2^(size-s);
        #A = N+1
            P.<x,y> = PolynomialRing(ZZ)
            pol = 1 + x * (A + y)  #构建的方程
 
            # Checking bounds
            #if debug:
                #print ("=== 核对数据 ===")
                #print ("* delta:", delta)
                #print ("* delta < 0.292", delta < 0.292)
                #print ("* size of e:", ceil(log(e)/log(2)))  # e的bit数
                # print ("* size of N:", len(bin(N)))          # N的bit数
                #print ("* size of N:", ceil(log(N)/log(2)))  # N的bit数
                #print ("* m:", m, ", t:", t)
 
            # boneh_durfee
            if debug:
                ##print ("=== running algorithm ===")
                start_time = time.time()
 
 
            solx, soly = boneh_durfee(pol, e, m, t, X, Y)
 
 
            if solx > 0:
                #print ("=== solution found ===")
                if False:
                    print ("x:", solx)
                    print ("y:", soly)
 
                d_sol = int(pol(solx, soly) / e)
                ss=ss+1
                print ("=== solution found ===")
                print ("p的高比特为:",l)
                print ("q的高比特为:",qM)
                print ("d=",d_sol) 
 
            if debug:
                print("=== %s seconds ===" % (time.time() - start_time))
            #break
        print("ss=",ss)
                            #end=time.process_time
        end=time.clock()
        print('Running time: %s Seconds'%(end-start))
if __name__ == "__main__":
    example()  
解出d
d = 815288165251971990144240125719456676622201418787728487985993940108011619486967079496288981
接着RSA解密
n = 123789043095302886784777548580725867919630872720308267296330863659260260632444171595208750648710642616709290340791408935502415290984231140635423328808872594955139658822363033096014857287439409252367248420356169878044065798634016290690979979625051287064109800759113475629317869327100941592970373827299442569489
e = 112070481298571389221611833986644006256566240788306316765530852688390558290807060037831460397016038678699757261874520899143918664293504728402666398893964929840011110057060969775245481057773655679041350091817099143204028098431544760662690479779286160425059494739419234859710815966582837874194763305328789592245
c = 63662561509209168743977531923281040338804656992093161358503738280395090747786427812762995865224617853709000826994250614233562094619845247321880231488631212423212167167713869682181551433686816142488666533035193128298379649809096863305651271646535125466745409868274019550361728139482502448613835444108383177119
d = 815288165251971990144240125719456676622201418787728487985993940108011619486967079496288981
m = pow(c,d,n)
flag = bytes.fromhex(hex(m)[2:])
print(flag)
Crypto2
题目:
# coding: utf-8
#!/usr/bin/env python2
import gmpy2
import random
import binascii
from hashlib import sha256
from sympy import nextprime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import long_to_bytes
from FLAG import flag
#flag = 'wdflag{123}'
def victory_encrypt(plaintext, key):
    key = key.upper()
    key_length = len(key)
    plaintext = plaintext.upper()
    ciphertext = ''
    for i, char in enumerate(plaintext):
        if char.isalpha():
            shift = ord(key[i % key_length]) - ord('A')
            encrypted_char = chr((ord(char) - ord('A') + shift) % 26 + ord('A'))
            ciphertext += encrypted_char
        else:
            ciphertext += char
    return ciphertext
victory_key = "WANGDINGCUP"
victory_encrypted_flag = victory_encrypt(flag, victory_key)
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
a = 0
b = 7
xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
G = (xG, yG)
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
h = 1
zero = (0,0)
dA = nextprime(random.randint(0, n))
if dA > n:
    print("warning!!")
def addition(t1, t2):
    if t1 == zero:
        return t2
    if t2 == zero:
        return t2
    (m1, n1) = t1
    (m2, n2) = t2
    if m1 == m2:
        if n1 == 0 or n1 != n2:
            return zero
        else:
            k = (3 * m1 * m1 + a) % p * gmpy2.invert(2 * n1 , p) % p
    else:
        k = (n2 - n1 + p) % p * gmpy2.invert((m2 - m1 + p) % p, p) % p
    m3 = (k * k % p - m1 - m2 + p * 2) % p
    n3 = (k * (m1 - m3) % p - n1 + p) % p
    return (int(m3),int(n3))
def multiplication(x, k):
    ans = zero
    t = 1
    while(t <= k):
        if (k &t )>0:
            ans = addition(ans, x)
        x = addition(x, x)
        t <<= 1
    return ans
def getrs(z, k):
    (xp, yp) = P
    r = xp
    s = (z + r * dA % n) % n * gmpy2.invert(k, n) % n
    return r,s
z1 = random.randint(0, p)
z2 = random.randint(0, p)
k = random.randint(0, n)
P = multiplication(G, k)
hA = multiplication(G, dA)
r1, s1 = getrs(z1, k)
r2, s2 = getrs(z2, k)
print("r1 = {}".format(r1))
print("r2 = {}".format(r2))
print("s1 = {}".format(s1))
print("s2 = {}".format(s2))
print("z1 = {}".format(z1))
print("z2 = {}".format(z2))
key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC)
iv = cipher.iv
encrypted_flag = cipher.encrypt(pad(victory_encrypted_flag.encode(), AES.block_size))
encrypted_flag_hex = binascii.hexlify(iv + encrypted_flag).decode('utf-8')
print("Encrypted flag (AES in CBC mode, hex):", encrypted_flag_hex)
# output
# r1 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
# r2 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
# s1 = 73636354334739290806716081380360143742414582638332132893041295586890856253300
# s2 = 64320109990895398581134015047131652648423777800538748939578192006599226954034
# z1 = 35311306706233977395060423051262119784421232920823462737043282589337379493964
# z2 = 101807556569342254666094290602497540565936025601030395061064067677254735341454
# ('Encrypted flag (AES in CBC mode, hex):', u'3cdbe372c9bc279e816336ad69b8247f4ec05647a7e97285dd64136875004b638b77191fe9bef702cb873ee93dbe376c050d0c721b69f17f539cff83372cc37b')
ECDSA 共k攻击求dA
 已知
  
     
      
       
        
        
          s 
         
        
          1 
         
        
       
         = 
        
       
         ( 
        
        
        
          z 
         
        
          1 
         
        
       
         + 
        
       
         r 
        
       
         ∗ 
        
       
         d 
        
       
         A 
        
       
         ) 
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
         ∗ 
        
        
        
          k 
         
         
         
           − 
          
         
           1 
          
         
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
      
        s_1 = (z_1+r*dA) \space mod \space n *k^{-1} \space mod \space n 
       
      
    s1=(z1+r∗dA) mod n∗k−1 mod n
  
     
      
       
        
        
          s 
         
        
          2 
         
        
       
         = 
        
       
         ( 
        
        
        
          z 
         
        
          2 
         
        
       
         + 
        
       
         r 
        
       
         ∗ 
        
       
         d 
        
       
         A 
        
       
         ) 
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
         ∗ 
        
        
        
          k 
         
         
         
           − 
          
         
           1 
          
         
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
      
        s_2 = (z_2+r*dA) \space mod \space n *k^{-1} \space mod \space n 
       
      
    s2=(z2+r∗dA) mod n∗k−1 mod n
 两边同时乘上k
  
     
      
       
        
        
          s 
         
        
          1 
         
        
       
         k 
        
       
         = 
        
       
         ( 
        
        
        
          z 
         
        
          1 
         
        
       
         + 
        
       
         r 
        
       
         ∗ 
        
       
         d 
        
       
         A 
        
       
         ) 
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
      
        s_1k = (z_1+r*dA) \space mod \space n 
       
      
    s1k=(z1+r∗dA) mod n
  
     
      
       
        
        
          s 
         
        
          2 
         
        
       
         k 
        
       
         = 
        
       
         ( 
        
        
        
          z 
         
        
          2 
         
        
       
         + 
        
       
         r 
        
       
         ∗ 
        
       
         d 
        
       
         A 
        
       
         ) 
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
      
        s_2k = (z_2+r*dA) \space mod \space n 
       
      
    s2k=(z2+r∗dA) mod n
 两式相减,得到k
  
     
      
       
       
         k 
        
       
         = 
        
       
         ( 
        
        
        
          s 
         
        
          2 
         
        
       
         − 
        
        
        
          s 
         
        
          1 
         
        
        
        
          ) 
         
         
         
           − 
          
         
           1 
          
         
        
       
         ( 
        
        
        
          z 
         
        
          2 
         
        
       
         − 
        
        
        
          z 
         
        
          1 
         
        
       
         ) 
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
      
        k = (s_2-s_1)^{-1}(z_2-z_1) \space mod \space n 
       
      
    k=(s2−s1)−1(z2−z1) mod n
 带入式子1,即可计算出dA
  
     
      
       
       
         d 
        
       
         A 
        
       
         = 
        
       
         ( 
        
        
        
          s 
         
        
          1 
         
        
       
         k 
        
       
         − 
        
        
        
          z 
         
        
          1 
         
        
       
         ) 
        
       
         × 
        
        
        
          k 
         
         
         
           − 
          
         
           1 
          
         
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
      
        dA = (s_1k-z_1)\times k^{-1} \space mod \space n 
       
      
    dA=(s1k−z1)×k−1 mod n
 之后直接计算出key和iv解AES密文即可
 然后根据加密代码逻辑还原明文
import gmpy2
from hashlib import sha256
from Crypto.Util.number import *
from Crypto.Cipher import AES
import binascii
def victory_decrypt(ciphertext, key):
    key = key.upper()
    key_length = len(key)
    plaintext = ''
    for i, char in enumerate(ciphertext):
        if char.isalpha():
            shift = ord(key[i % key_length]) - ord('A')
            decrypted_char = chr((ord(char) - ord('A') - shift + 26) % 26 + ord('A'))
            plaintext += decrypted_char
        else:
            plaintext += char
    return plaintext
r1 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
r2 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
s1 = 73636354334739290806716081380360143742414582638332132893041295586890856253300
s2 = 64320109990895398581134015047131652648423777800538748939578192006599226954034
z1 = 35311306706233977395060423051262119784421232920823462737043282589337379493964
z2 = 101807556569342254666094290602497540565936025601030395061064067677254735341454
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
c = '3cdbe372c9bc279e816336ad69b8247f4ec05647a7e97285dd64136875004b638b77191fe9bef702cb873ee93dbe376c050d0c721b69f17f539cff83372cc37b'
k = (z2-z1)*gmpy2.invert(s2-s1,n) %n
dA = (s1*k-z1)*gmpy2.invert(r1,n)%n
key = sha256(long_to_bytes(dA)).digest()
iv = binascii.unhexlify(c[:32])
enc = binascii.unhexlify(c[32:])
cipher = AES.new(key, AES.MODE_CBC,iv)
flag = cipher.decrypt(enc)
print(flag)
#SDSRDO{34697E430N6H6URW68849Q8HWT81039J}
ciphertext = "SDSRDO{34697E430N6H6URW68849Q8HWT81039J}"
victory_key = "WANGDINGCUP"
decrypted_flag = victory_decrypt(ciphertext, victory_key)
print("Decrypted flag:", decrypted_flag)
#WDFLAG{34697E430F6B6ACA68849D8FCE81039B}
白虎组
Crypto1
先ddl了,有时间再补上
Crypto2
题目:
from Crypto.Util.number import getPrime, isPrime, GCD, inverse
nbits = 2048
gbits = 1000
g = getPrime(int(gbits))
while True:
    a = getPrime(int(nbits*0.5)-gbits)
    p = 2*g*a + 1
    if isPrime(p):
        break
while True:
    b = getPrime(int(nbits*0.5)-gbits)
    q = 2*g*b + 1
    if p!=q and isPrime(q):
        break
N = p*q
e = 65537
def str2int(s):
    return int(s.encode('latin-1').hex(),16)
def int2str(i):
    tmp=hex(i)[2:]
    if len(tmp)%2==1:
        tmp='0'+tmp
    return bytes.fromhex(tmp).decode('latin-1')
with open('pubkey.txt','w') as f:
    f.write(str(e)+'\n')
    f.write(str(N)+'\n')
with open('flag.txt') as f:
    plain = str2int(f.read())
c = pow(plain,e,N)
with open('cipher.txt','wb') as f:
    f.write(int2str(c).encode('latin-1'))
分析代码,我们可以发现p和q的生成都存在一个共同的因子g,约为1000bit
 又 
     
      
       
       
         ∵ 
        
       
         p 
        
       
         = 
        
       
         2 
        
       
         g 
        
       
         a 
        
       
         + 
        
       
         1 
        
       
         , 
        
       
         q 
        
       
         = 
        
       
         2 
        
       
         g 
        
       
         b 
        
       
         + 
        
       
         1 
        
       
      
        \because p = 2ga+1,q = 2gb+1 
       
      
    ∵p=2ga+1,q=2gb+1
  
     
      
       
       
         ⇒ 
        
       
         g 
        
       
         = 
        
       
         g 
        
       
         c 
        
       
         d 
        
       
         ( 
        
       
         p 
        
       
         − 
        
       
         1 
        
       
         , 
        
       
         q 
        
       
         − 
        
       
         1 
        
       
         ) 
        
       
      
        \Rightarrow g = gcd(p-1,q-1) 
       
      
    ⇒g=gcd(p−1,q−1)
 所以我们可以使用Pollard’s rho来分解n,从而求得p和q
 最后再把密文处理成整数型,然后计算出phi,d解密即可获得flag
 exp:
import gmpy2
from Crypto.Util.number import *
def f(x, n):
    return (pow(x, n - 1, n) + 3) % n
def rho(n):
    i = 1
    while True:
        a = getRandomRange(2, n)
        b = f(a, n)
        j = 1
        while True:
            p = GCD(abs(a - b), n)
            print('{} in {} circle'.format(j, i))
            if p == n:
                break
            elif p > 1:
                return (p, n // p)
            else:
                a = f(a, n)
                b = f(f(b, n), n)
            j += 1
        i += 1
#将密文转换整型
with open('cipher.txt', 'rb') as f:
    c_bytes = f.read()  # 读取字节内容
    c_hex = c_bytes.hex()  # 将字节转换为十六进制字符串
    c = int(c_hex, 16)  # 将十六进制字符串转换为整数
e = 65537
n = 49025724928152491719950645039355675823887062840095001672970308684156817293484070166684235178364916522473822184239221170514602692903302575847326054102901449806271709230774063675539139201327878971370342483682454617270705142999317092151456200639975738970405158598235961567646064089356496022247689989925574384915789399433283855087561428970245448888799812611301566886173165074558800757040196846800189738355799057422298556992606146766063202605288257843684190291545600282197788724944382475099313284546776350595539129553760118549158103804149179701853798084612143809757187033897573787135477889183344944579834942896249251191453
#Pollard’s rho分解n,
#p,q = rho(n)
p = 181081097501198023069853833182353184261284123229534078254107942099502325869566163846505417960576038861954213847321685798395883194037860319430010178354074600519049325312842897561278830450748961589667396822373094094674865532726953310816962745801088563041800719074771895743022649725941252134035150899684475275107
q = 270739053411293468044358005572326880715866131246316305975150551797771999927260913691624449594733673350641598358977228099278925982221096409496197961213452575581038864123668037331549492912118266914139408344450017736857756347795681452284667629499583154669046006953194443040693208729068117415444168170452989294079
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
flag = long_to_bytes(m)
print(flag)
朱雀组
Crypto2
题目给了密文c,n以及p,其中p的高256bit已知
 显然这是一个p高位泄露的题型,但是卡界了。
 这一类题,我在2023 LitCTF 的baby_xor一题中出过一样的考点,详情移步下方链接,这里就不细讲了。
 2023 LitCTF — Crypto wp
from tqdm import *
n = 0x00b8cb1cca99b6ac41876c18845732a5cbfc875df346ee9002ce608508b5fcf6b60a5ac7722a2d64ef74e1443a338e70a73e63a303f3ac9adf198595699f6e9f30c009d219c7d98c4ec84203610834029c79567efc08f66b4bc3f564bfb571546a06b7e48fb35bb9ccea9a2cd44349f829242078dfa64d525927bfd55d099c024f
ph = 0xe700568ff506bd5892af92592125e06cbe9bd45dfeafe931a333c13463023d4f0000000000000000000000000000000000000000000000000000000000000000
pbits = 512
p_high = ph>>256
for i in trange(2**8):
    p4 = p_high<<8
    p4 = p4 + i
    kbits = pbits - p4.nbits()
    p4 = p4 << kbits
    PR.<x> = PolynomialRing(Zmod(n))
    f = x + p4
    roots = f.small_roots(X=2^kbits, beta=0.4, epsilon=0.01)
    if roots:        
        p = p4+int(roots[0]) 
        if n%p==0:
            print(i,p)
            break
爆破得到
i = 194 
p = 12098520864598198757294135341465388062087431109285224283440314414683283061468500249596026217234382854875647811812632201834942205849073893715844547051090363
from Crypto.Util.number import *
import gmpy2
import libnum
f = open("flag.enc","rb").read()
c = bytes_to_long(f)
p = 12098520864598198757294135341465388062087431109285224283440314414683283061468500249596026217234382854875647811812632201834942205849073893715844547051090363
n = 0x00b8cb1cca99b6ac41876c18845732a5cbfc875df346ee9002ce608508b5fcf6b60a5ac7722a2d64ef74e1443a338e70a73e63a303f3ac9adf198595699f6e9f30c009d219c7d98c4ec84203610834029c79567efc08f66b4bc3f564bfb571546a06b7e48fb35bb9ccea9a2cd44349f829242078dfa64d525927bfd55d099c024f
e = 65537
q = n//p
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
flag = long_to_bytes(m)
print(flag)
之后计算出q = n//p,把密文变成数字型,再RSA解密即可得到flag
Crypto3
part1
 
     
      
       
        
        
          n 
         
        
          1 
         
        
       
         ≈ 
        
        
        
          p 
         
        
          1 
         
        
       
         × 
        
       
         2024 
        
        
        
          p 
         
        
          1 
         
        
       
         ≈ 
        
       
         2024 
        
        
        
          p 
         
        
          1 
         
        
          2 
         
        
       
      
        n_1 \approx p_1 \times 2024p_1 \approx 2024p_1^{2} 
       
      
    n1≈p1×2024p1≈2024p12
 整除2024,然后对n1开方即可得到p1,进而得到q1
n1 = 
p1 = gmpy2.iroot(n1//2024,2)[0]
q1 = n1//p1
得到p1和q1
p1 = 146187607535300384587509957494226602879910697731111793338231366571998962914635615996598727004205169961576448628561413122161261394771744901435074146079222198287010135623393031759366562782057113205707175142954551779767710913840908209285742147746099427389400973759220801645310208401376788865791190217328962123279
q1 = 295883717651447978405120153968314644228939252207770269716580285941725900939222486777115823456511264002230732024208300159254393063018011680504590071664345729332908514501747496280957923070883597128351322489340012802249846889613998215594342107038105241036147570888662902530107861804386620664361368999873819337516721
part2
已知
  
     
      
       
        
        
          n 
         
        
          2 
         
        
       
         = 
        
        
        
          p 
         
        
          2 
         
        
       
         ∗ 
        
        
        
          q 
         
        
          2 
         
        
       
         , 
        
        
        
          n 
         
        
          22 
         
        
       
         = 
        
        
        
          p 
         
        
          2 
         
        
          2 
         
        
       
         + 
        
        
        
          q 
         
        
          2 
         
        
          2 
         
        
       
      
        n_2 = p_2*q_2,n_{22} = p_2^{2}+q_2^{2} 
       
      
    n2=p2∗q2,n22=p22+q22
 那么我们直接构建方程组解方程即可
n2 = 
n22 = 
p2,q2 = Ints('p2 q2')
s = Solver()
s.add(p2*q2==n2)
s.add(p2**2+q2**2==n22)
if s.check()==sat:
    print(s.model())
   
得到p2和q2
p2 = 133064204383114442564887327191574256650055020929830824588577417753167292659660059589564610129957808064002805580421156153609277092389753135192904997169182787255213644860856072991606212800442053226675120936710208060680648681274616282517421189570805017586256581334157425386374483509501090965717646720700424863423
q2 = 161350628589676557525881716966340935717969334783533837289612088856244362686139907887162014592790132128414148723412888028361068777482425667132948875411222080236173967775667519908708279765880512473014384298105752518090429868307024159426520644435015258039304108930727310884096853455754839248318020906028016894579
part3
根据p3和q3得生成代码,可知
  
     
      
       
        
        
          p 
         
        
          3 
         
        
       
         + 
        
        
        
          q 
         
        
          3 
         
        
       
         = 
        
       
         2 
        
       
         ( 
        
        
         
         
           n 
          
         
           3 
          
         
        
       
         + 
        
       
         1 
        
       
         ) 
        
       
      
        p_3+q_3 = 2(\sqrt{n_3}+1) 
       
      
    p3+q3=2(n3+1)
 再联合
  
     
      
       
        
        
          n 
         
        
          3 
         
        
       
         = 
        
        
        
          p 
         
        
          3 
         
        
        
        
          q 
         
        
          3 
         
        
       
      
        n_3 = p_3q_3 
       
      
    n3=p3q3
 可以构造方程组计算出p3和q3
n3 = 
tmp = gmpy2.iroot(n3,2)[0]
p3,q3 = Ints('p3 q3')
s = Solver()
s.add(p3*q3==n3)
s.add(p3+q3==2*tmp+2)
if s.check()==sat:
    print(s.model())
得到p3和q3
p3 = 122919460677181447255662000442101333281019894158297462412806821518657755917099521145678690717375396316626833583612356812214587401412448220563982839146665862717678495178437386577882720343715419646347453965273307650714361987001939787363067549306301977112348400269518912107383153989960205330328806948574142432881
q3 = 122919460677181447255662000442101333281019894158297462412806821518657755917099521145678690717375396316626833583612356812214587401412448220563982839146665862719627439871738815429215471546402837328038925028763750154507765739783853121032116043651820874648359779165148305098515735172075366847764584719616506196289
part4
已知
  
     
      
       
        
        
          m 
         
        
          1 
         
        
       
         = 
        
        
        
          p 
         
        
          1 
         
        
        
        
          m 
         
        
          2 
         
        
       
         + 
        
        
        
          p 
         
        
          2 
         
        
       
         m 
        
       
         + 
        
        
        
          p 
         
        
          3 
         
        
       
      
        m_1 = p_1m^2+p_2m+p_3 
       
      
    m1=p1m2+p2m+p3
  
     
      
       
        
        
          m 
         
        
          2 
         
        
       
         = 
        
        
        
          q 
         
        
          1 
         
        
        
        
          m 
         
        
          2 
         
        
       
         + 
        
        
        
          q 
         
        
          2 
         
        
       
         m 
        
       
         + 
        
        
        
          q 
         
        
          3 
         
        
       
      
        m_2 = q_1m^2+q_2m+q_3 
       
      
    m2=q1m2+q2m+q3
  
     
      
       
        
        
          c 
         
        
          1 
         
        
       
         = 
        
        
        
          m 
         
        
          1 
         
        
          e 
         
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
      
        c_1 = m_1^e \space mod \space n 
       
      
    c1=m1e mod n
  
     
      
       
        
        
          c 
         
        
          2 
         
        
       
         = 
        
        
        
          m 
         
        
          2 
         
        
          e 
         
        
       
           
        
       
         m 
        
       
         o 
        
       
         d 
        
       
           
        
       
         n 
        
       
      
        c_2 = m_2^e \space mod \space n 
       
      
    c2=m2e mod n
 一眼顶针 Franklin-Reiter攻击,但是e = 2999,有点大,不太好多项式GCD,所以我们使用half gcd来加速多项式得gcd
#sage
from Crypto.Util.number import *
import sys
def HGCD(a, b):
    if 2 * b.degree() <= a.degree() or a.degree() == 1:
        return 1, 0, 0, 1
    m = a.degree() // 2
    a_top, a_bot = a.quo_rem(x^m)
    b_top, b_bot = b.quo_rem(x^m)
    R00, R01, R10, R11 = HGCD(a_top, b_top)
    c = R00 * a + R01 * b
    d = R10 * a + R11 * b
    q, e = c.quo_rem(d)
    d_top, d_bot = d.quo_rem(x^(m // 2))
    e_top, e_bot = e.quo_rem(x^(m // 2))
    S00, S01, S10, S11 = HGCD(d_top, e_top)
    RET00 = S01 * R00 + (S00 - q * S01) * R10
    RET01 = S01 * R01 + (S00 - q * S01) * R11
    RET10 = S11 * R00 + (S10 - q * S11) * R10
    RET11 = S11 * R01 + (S10 - q * S11) * R11
    return RET00, RET01, RET10, RET11
    
def GCD(a, b):
    q, r = a.quo_rem(b)
    if r == 0:
        return b
    R00, R01, R10, R11 = HGCD(a, b)
    c = R00 * a + R01 * b
    d = R10 * a + R11 * b
    if d == 0:
        return c.monic()
    q, r = c.quo_rem(d)
    if r == 0:
        return d
    return GCD(d, r)
sys.setrecursionlimit(500000)
p1 = 146187607535300384587509957494226602879910697731111793338231366571998962914635615996598727004205169961576448628561413122161261394771744901435074146079222198287010135623393031759366562782057113205707175142954551779767710913840908209285742147746099427389400973759220801645310208401376788865791190217328962123279
q1 = 295883717651447978405120153968314644228939252207770269716580285941725900939222486777115823456511264002230732024208300159254393063018011680504590071664345729332908514501747496280957923070883597128351322489340012802249846889613998215594342107038105241036147570888662902530107861804386620664361368999873819337516721
p2 = 133064204383114442564887327191574256650055020929830824588577417753167292659660059589564610129957808064002805580421156153609277092389753135192904997169182787255213644860856072991606212800442053226675120936710208060680648681274616282517421189570805017586256581334157425386374483509501090965717646720700424863423
q2 = 161350628589676557525881716966340935717969334783533837289612088856244362686139907887162014592790132128414148723412888028361068777482425667132948875411222080236173967775667519908708279765880512473014384298105752518090429868307024159426520644435015258039304108930727310884096853455754839248318020906028016894579
p3 = 122919460677181447255662000442101333281019894158297462412806821518657755917099521145678690717375396316626833583612356812214587401412448220563982839146665862717678495178437386577882720343715419646347453965273307650714361987001939787363067549306301977112348400269518912107383153989960205330328806948574142432881
q3 = 122919460677181447255662000442101333281019894158297462412806821518657755917099521145678690717375396316626833583612356812214587401412448220563982839146665862719627439871738815429215471546402837328038925028763750154507765739783853121032116043651820874648359779165148305098515735172075366847764584719616506196289
e = 2999
n = 16384707752002961811357426356040804358820450429112719059482965460688633224199445850016434753713403979835193345762008018698844949530549502743281731789334994428312464772130516824285978243651287411553116255652677650004040824347186268439788928865418368468897627214552572846541839629323949068937120798767586917684764944219031287061253819651989184659516095370231858355076296906499453937821927440892978892852470311395853382511321806654834173438462402181182706548632711364029421502619027705821496435350762046222825598323497861393301677598992958820184003364763320507041485736186970914568690758845870075203051617037883827279119
c1 = 11382473352009511791762101735529507838446758824791351775250810654314066423650685628073502579664186057184344713574429940611514864513995383801386486394825452589218688059897458368223518637647179221771655104137667329953446341815527699304599435283634443556038985090968474934734321344125280569467142049038929368549733232047316780077686016318662303350081357699377969335914292631398295061602601940464649624118295616080162917211435856653333110858004250959483891522407923876955812205685375843940874486371994485161526059198019014530740524036481557433830304867422828002361446861419824025752025995296741718962141953713234949894732
c2 = 13291355062242181017235433629558689027068114611650872691659197232933062720760260933280099178334615566562244698391494264051061145257215694115131167336658805533954362024110598093368016089512260336234014588390607552801658614571912470713860293915607463462319165043506295500174873235810829299741016973929360670488678562024980338443636210602228872744449850339238513161642644630785241443001404597604581629303749287855365022218361488602768556292856610619067231689100946362621816109192111615866980116556776737918323907474176583284350758109722993772794866722135312051956704194889790127430725508449097365193657563726357277350509
R.<x> = PolynomialRing(Zmod(n))
f = (p1 * x * x + p2 * x + p3)^e - c1
g = (q1 * x * x + q2 * x + q3)^e - c2
res = GCD(f,g)
m = -res.monic().coefficients()[0]
flag = long_to_bytes(int(m))
print(flag)
【许多的故事,大大小小的,末尾就两个字,“还好”。而”还好“的注解,大概就是”希望“。】



















