Fork me on GitHub

Buuctf Crypto 刷题记录

Buuctf Crypto 刷题记录

写在前面

  • 实习入职,要求继续做比赛crypto方向赛题,由于长时间未接触了,所以现在不得不好好复习一下

[V&N2020 公开赛]easy_RSA

考点

  • 平滑大素数分解:使用primefac库可以选取威尔逊定理分解
  • rabbin算法
  • legendre算法
  • tonelli算法

分析

def getprime(bits):
    while 1:
        n = 1
        while n.bit_length() < bits:
            n *= next_prime(randint(1,1000))
        if isPrime(n - 1):
            return n - 1
  • “题如其名”,真是够easy
  • 先看素数生成部分函数定义,大素数n是由较小的素数进行连乘后减一所得,这个处理方式和之前有一道用到Williams’p+1 algorithm的题目很相似,这次在参考网上的wp时发现了可以直接调用库分解,这给我们这种数学菜鸡终于有了一条活路
  • 首先使用primefac库选择Williams’p+1 algorithm分解,命令如下:
python -m primefac -vs -m=p+1 7941371739956577280160664419383740967516918938781306610817149744988379280561359039016508679365806108722198157199058807892703837558280678711420411242914059658055366348123106473335186505617418956630780649894945233345985279471106888635177256011468979083320605103256178446993230320443790240285158260236926519042413378204298514714890725325831769281505530787739922007367026883959544239568886349070557272869042275528961483412544495589811933856131557221673534170105409
参数详解:
-m : python使用命令行直接执行模块参数
-vs : 可选参数 [ -v | --verbose ]  [ -s | --summary ] ,-v和-s标志可被组合成以任何顺序单个标志
-m=p+1 : 选用威尔逊定理 -m =标志控,期间使用的功能多因素相。选项分别是prb,p-1,p + 1,ecm和mpqs,分别表示Pollard的rho,Pollard的p -1,Williams的p +1,椭圆曲线法和多项式二次筛。
详细用法见:https://pypi.org/project/primefac/
  • d = invert(q ** 2, p ** 2)
  • 这里解出p之后,可以就可以根据给出的d,直接求逆算出q,但由于q>p的所以应是还要加上p的倍数
q2=gmpy2.invert(d,p**2)

for i in range(10000):
    q=gmpy2.iroot(q2+i*p**2,2)
    if(q[1]==1): # iroot()返回的是一个tuple,(mpz(xxx),true),若能开方出来则会返回true
        print(q[0],i)
        break
q=q[0]
  • 对于r直接用n除一下就行了
  • 至此所有参数都可以获得了,再看flag的加密方式可以发现是先有加密生成参数c,而后再由c加密生成给出的密文chiper
  • 这里先解决ccrsa加密形成给出的chiper,这里直接用正常的rsa思路算出c就行
phi = (p-1)*(q-1)*(r-1)

d1=gmpy2.invert(e,phi)

c1 = pow(chiper,d1,n)
  • 三数连乘的欧拉函数,参考nsctf-2019-techworldϕ(p*q*r)=ϕ(N)=ϕ(q)*ϕ(p)*ϕ(r)=(p−1)*(q−1)*(r−1)即可
  • 算出c1之后即可根据托内利-克斯算法:用于解决合数模问题 即r ** 2 = n mod p => pow(r,2,p)还原出flag
  • 算法参考
    https://blog.csdn.net/weixin_44617902/article/details/112785051
  • 完整代码
# coding:utf-8
from gmpy2 import *
from Crypto.Util.number import long_to_bytes'

p=102634610559478918970860957918259981057327949366949344137104804864768237961662136189827166317524151288799657758536256924609797810164397005081733039415393
n=7941371739956577280160664419383740967516918938781306610817149744988379280561359039016508679365806108722198157199058807892703837558280678711420411242914059658055366348123106473335186505617418956630780649894945233345985279471106888635177256011468979083320605103256178446993230320443790240285158260236926519042413378204298514714890725325831769281505530787739922007367026883959544239568886349070557272869042275528961483412544495589811933856131557221673534170105409
e = 0x10001
d=7515987842794170949444517202158067021118454558360145030399453487603693522695746732547224100845570119375977629070702308991221388721952258969752305904378724402002545947182529859604584400048983091861594720299791743887521228492714135449584003054386457751933095902983841246048952155097668245322664318518861440
chiper=1618155233923718966393124032999431934705026408748451436388483012584983753140040289666712916510617403356206112730613485227084128314043665913357106301736817062412927135716281544348612150328867226515184078966397180771624148797528036548243343316501503364783092550480439749404301122277056732857399413805293899249313045684662146333448668209567898831091274930053147799756622844119463942087160062353526056879436998061803187343431081504474584816590199768034450005448200

q2=invert(d,p**2)

for i in range(10000):
    q=iroot(q2+i*p**2,2)
    if(q[1]==1): # iroot()返回的是一个tuple,(mpz(xxx),true),若能开方出来则会返回true
        print(q[0],i)
        break
q=q[0]
r=n//p//q

phi = (p-1)*(q-1)*(r-1)

d1=invert(e,phi)

c1 = pow(chiper,d1,n)

def legendre(a, p): # 勒让德符号 a ** ((p-1)//2) mod p ,解决平方剩余问题
    return pow(a, (p - 1) // 2, p)


def tonelli(n, p): # 托内利-克斯算法:用于解决合数模问题 即r ** 2 = n mod p => pow(r,2,p)
    assert legendre(n, p) == 1
    q = p - 1
    s = 0
    while q % 2 == 0:
        q //= 2
        s += 1
    if s == 1:
        return pow(n, (p + 1) // 4, p)
    for z in range(2, 10000):
#    for z in range(2, p):
        if p - 1 == legendre(z, p):
            break
    c = pow(z, q, p)
    r = pow(n, (q + 1) // 2, p)
    t = pow(n, q, p)
    m = s
    t2 = 0
    while (t - 1) % p != 0:
        t2 = (t * t) % p
        for i in range(1, m):
            if (t2 - 1) % p == 0:
                break
            t2 = (t2 * t2) % p
        b = pow(c, 1 << (m - i - 1), p)
        r = (r * b) % p
        c = (b * b) % p
        t = (t * c) % p
        m = i
    return r

m = tonelli(c1,r)

print(''.join(long_to_bytes(m)))

[GKCTF2020]babycrypto

考点

  • Factoring with high bits known Attack

分析

  • 密文除了p给出的方式有些奇怪,其余的都比较正常,百度直接搜,发现是已知高位攻击,根据https://github.com/Zui-Qing-Feng/RSA/blob/master/03.Factoring%20with%20high%20bits%20known%20Attack修改位数为128即可解出p
sage:n=0xb119849bc4523e49c6c038a509a74cda628d4ca0e4d0f28e677d57f3c3c7d0d876ef07d7581fe05a060546fedd7d061d3bc70d679b6c5dd9bc66c5bdad8f2ef898b1e785496c4989daf716a1c89d5c174da494eee7061bcb6d52cafa337fc2a7bba42c918bbd3104dff62ecc9d3704a455a6ce282de0d8129e26c840734ffd302bec5f0a66e0e6d00b5c50fa57c546cff9d7e6a978db77997082b4cb927df9847dfffef55138cb946c62c9f09b968033745b5b6868338c64819a8e92a827265f9abd409359a9471d8c3a2631b80e5b462ba42336717700998ff38536c2436e24ac19228cd2d7a909ead1a8494ff6c3a7151e888e115b68cc6a7a8c6cf8a6c005L
sage:p_fake=0xe4e4b390c1d201dae2c00a4669c0865cc5767bc444f5d310f3cfc75872d96feb89e556972c99ae20753e3314240a52df5dccd076a47c6b5d11b531b92d901b2b512aeb0b263bbfd624fe3d52e5e238beeb581ebe012b2f176a4ffd1e0d2aa8c4d3a2656573b727d4d3136513a931428b00000000000000000000000000000000L
sage: pbits=1024
sage: kbits=128
sage: pbar=p_fake & (2^pbits-2^kbits)
sage: print("upper %d bits (of %d bits) is given" % (pbits-kbits,pbits))
upper 896 bits (of 1024 bits) is given
sage: PR.<x> = PolynomialRing(Zmod(n))
sage: f=x+pbar
sage: x0=f.small_roots(X=2^kbits,beta=0.4)[0]
sage: print(hex(int(x0+pbar)))
0xe4e4b390c1d201dae2c00a4669c0865cc5767bc444f5d310f3cfc75872d96feb89e556972c99ae20753e3314240a52df5dccd076a47c6b5d11b531b92d901b2b512aeb0b263bbfd624fe3d52e5e238beeb581ebe012b2f176a4ffd1e0d2aa8c4d3a2656573b727d4d3136513a931428b92826225b6d0e735440b613a8336ffa3L
  • 解出p剩下就是常规rsa
import gmpy2
from Crypto.Util.number import *
p1=160734387026849747944319274262095716650717626398118440194223452208652532694713113062084219512359968722796763029072117463281356654614167941930993838521563406258263299846297499190884495560744873319814150988520868951045961906000066805136724505347218275230562125457122462589771119429631727404626489634314291445667L
p2=0xe4e4b390c1d201dae2c00a4669c0865cc5767bc444f5d310f3cfc75872d96feb89e556972c99ae20753e3314240a52df5dccd076a47c6b5d11b531b92d901b2b512aeb0b263bbfd624fe3d52e5e238beeb581ebe012b2f176a4ffd1e0d2aa8c4d3a2656573b727d4d3136513a931428b92826225b6d0e735440b613a8336ffa3
n2=0xb119849bc4523e49c6c038a509a74cda628d4ca0e4d0f28e677d57f3c3c7d0d876ef07d7581fe05a060546fedd7d061d3bc70d679b6c5dd9bc66c5bdad8f2ef898b1e785496c4989daf716a1c89d5c174da494eee7061bcb6d52cafa337fc2a7bba42c918bbd3104dff62ecc9d3704a455a6ce282de0d8129e26c840734ffd302bec5f0a66e0e6d00b5c50fa57c546cff9d7e6a978db77997082b4cb927df9847dfffef55138cb946c62c9f09b968033745b5b6868338c64819a8e92a827265f9abd409359a9471d8c3a2631b80e5b462ba42336717700998ff38536c2436e24ac19228cd2d7a909ead1a8494ff6c3a7151e888e115b68cc6a7a8c6cf8a6c005L
e=65537
q2=n2//p2
d=gmpy2.invert(e,(p2-1)*(q2-1))
m2=pow(c,d,n)
print(long_to_bytes(m2))

[GKCTF2020]Backdoor

考点

  • rsa公玥文件
  • base64加密

分析

  • 给出三个文件,一个flag密文,一个公玥文件,源码
  • 常规题,直接用openssl提取ne
    openssl rsa -pubin -text -modulus -in warmip -in pub.pem
RSA Public-Key: (443 bit)
Modulus:
    05:77:47:96:b3:01:e1:c7:f4:0b:49:45:05:68:8b:
    1f:de:21:f6:d5:ff:ce:63:6f:f1:67:d8:5e:37:d7:
    a7:b7:49:3e:33:c1:7d:44:17:a2:5c:a2:4a:67:16:
    31:4c:f1:86:e1:69:96:dc:fc:67:9b
Exponent: 65537 (0x10001)
Modulus=5774796B301E1C7F40B494505688B1FDE21F6D5FFCE636FF167D85E37D7A7B7493E33C17D4417A25CA24A6716314CF186E16996DCFC679B
writing RSA key
-----BEGIN PUBLIC KEY-----
MFMwDQYJKoZIhvcNAQEBBQADQgAwPwI4BXdHlrMB4cf0C0lFBWiLH94h9tX/zmNv
8WfYXjfXp7dJPjPBfUQXolyiSmcWMUzxhuFpltz8Z5sCAwEAAQ==
-----END PUBLIC KEY-----
  • Modulus即为n,e直接可以读出
n=5774796B301E1C7F40B494505688B1FDE21F6D5FFCE636FF167D85E37D7A7B7493E33C17D4417A25CA24A6716314CF186E16996DCFC679B
e=65537
  • n比较小直接分解即可,剩下来就是常规rsa
import gmpy2
from Crypto.Util.number import *
n=15518961041625074876182404585394098781487141059285455927024321276783831122168745076359780343078011216480587575072479784829258678691739L
p=3386619977051114637303328519173627165817832179845212640767197001941
q=4582433561127855310805294456657993281782662645116543024537051682479
c=5902102609936183530036413041949205016072856184947596155784933422689438216690059498706287388882989673839294236821030261398121787376802
e=65537
d=gmpy2.invert(e,(p-1)*(q-1))
m=pow(c,d,n)
print(long_to_bytes(m))
posted @ 2021-03-28 18:18  Konmu  阅读(778)  评论(0编辑  收藏  举报