ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Buuctf Crypto 刷题记录

2021-03-28 18:33:40  阅读:527  来源: 互联网

标签:Buuctf gmpy2 pow invert sage Crypto t2 bits 刷题


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))

标签:Buuctf,gmpy2,pow,invert,sage,Crypto,t2,bits,刷题
来源: https://www.cnblogs.com/Konmu/p/14589379.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有