野题
题目来源:B站风二西老师!
链接: B站参考视频
考点:费马小定理 RSA
解题:
题目源代码:
from Crypto.Util.number import *
from random import *
from flag import FLAG
BITS = 1024
flag = bytes_to_long(FLAG)
p = getPrime(BITS)
q = getPrime(BITS)
n = p*q
#得到一个1到n之间的随机整数
g = randint(1,n)
a1 = randint(1,n)
a2 = randint(1,n)
k1 = pow(g,a1*(p-1),n)
k2 = pow(g,a2*(q-1),n)
print("n = %s"%n)
print("k1 = %s"%k1)
print("k2 = %s"%k2)
b1 = randint(1,n)
b2 = randint(1,n)
c1 = (pow(k1,b1,n)*flag)%n
c2 = (pow(k1,b2,n)*flag)%n
#断言语句提示 flag是小于n的
assert flag < n
print("c1 = %d"%c1)
print("c2 = %d"%c2)
'''
n = 9858036118742475059433629759400140149605427966433887001108914046633590983713890376353399251885596714047941627222518567515364827340623251995233155278723954926352575221234142199002389819918370754455018819109203109519495493316781422680537687252828642561153832774006286448224016306003631037545643746379044035822029246823483754854602215035869280453855199171915302879406862793807947285344105991067005185493038370882005106069286893165426035453262949739088328689761676541415552066845538243916687080015277379248062286846119847500455125785281216888979581104100416760176854106890525904804003871967844912776926419778292365918733
k1 = 4961356980843219227031667558158760111429474781353239042846946454889308337426649950562701556812878479419482114480334396560017050901408543482904510839046375272618911899662922000275482705215097956326853000314956770940510205507508883917322367747195211326932972446951696070952604655668087834669239815290687449340666091764203568518066586476150861542456340936303824392273004883320273039066213750777751436497551151274574369325153858390731248298056433816285354182588883715211738843801326831297181947562239993323202961410530072969013398669658073337273085171642258091164822631807295793886169033827781164115751086585872189121242
k2 = 8943660577405892997099415246000964332413663135286363632645590478753346989578467429954062835807609942851365774880023144520942029315601785638267996044694835031239940919206726351387647791985293576677117144309222345482756402074345845506698221273703274410853004407629888264128027446878663894377503365831077629911487977796118893231354280680598325548327444053575447407791091256260091884824630356121390983373431984667887019137026219503921285289004358685317477667095203722657823621429988685962573778350234701781053232256494914398637744373081735647622790113318562356606831868682912936768762749860591989864642992367932846710665
c1 = 4115578106197062017294044310891024039554438131787269391154862526142866937938155870549829472424386226484625850457327387070755337288822640509004443484397234720914851433620556887385729540499953724033259937785600491548446806766462413179765702810698096381537513314758346885921106310631278002150697458246447235914052771405341899822588463120295331632180131956205362147784798497203957828308109092025630961803808101730731656980785388965672073473370194469269645377465298620585379296063436880502566076330461976785816470877632107769103280243111778113065038163250625042092690628478547757779278811188187028242267396799577953511519
c2 = 1069417390392712224013484466911946251479515132512683148923109806683426116132220974153759944203026795479272077929265429391851629949467649257513543604050970026412281764244254971122378729482985044535740328359563865949603944075625096242664299209143911115287867129678168308056632406522013494918385694044348658310785409548526884085469813804712945302487796400392901241763662852123731910949146709219711388725430757562836225353975933990961286601256351973981732004724397292031523206145692402321288085912884435326461626793886145952474077975796841103796283781865005879515976167187625178845457630564285181509041968859289264784559
'''
我们首先关注到flag所在语句 找到和已知变量和前式的关系
k1 = pow(g,a1*(p-1),n)
k1 = ga1*(p-1) %n = (ga1)(p-1) %n
当我们看到一个数的(p-1)次方 自然联想到费马小定理
p是素数,有
a(p-1) % p = 1
ap % p = a % p
所以对k1继续操作
k1 = (ga1)(p-1) + k*n
两边同时模p
k1%p = ((ga1)(p-1) + kn)%p = (ga1)(p-1) %p+ kn%p
因为n=p*q
k1%p = (ga1)(p-1) %p
此时ga1就相当于费马小定理中的a 故k1%p = 1
即有 k1 = 1 + k*p
故k1 - 1 = k * p
并且n = q * p
此时我们发现k1-1和n有公约数p 并且k1 - 1和 n均已知
p = gcd(k1-1,n)
此时得到k1的相关式子 然后看flag的相关
c1 = (pow(k1,b1,n)*flag)%n
c1 = ((k1b1 % n)*flag)%n = ((k1b1 % n)*flag) + k*n
同样两边模p
c1%p = ((k1b1 + k*n)*flag) %p
c1%p = ((k1b1 + k*n)%p*flag%p)
c1%p = ((k1b1%p + k*n%p)*flag%p)
c1%p = (k1b1 %p*flag%p)
c1%p = ((k1%p)b1 %p*flag%p)
由第一部分已知k1%p = 1
所以c1%p=flag%p
又因为断言语句assert flag < n
所以flag一定小于p 模p就等于其本身
故 flag = (c1 % p)
exp:
import gmpy2
import libnum
n = 9858036118742475059433629759400140149605427966433887001108914046633590983713890376353399251885596714047941627222518567515364827340623251995233155278723954926352575221234142199002389819918370754455018819109203109519495493316781422680537687252828642561153832774006286448224016306003631037545643746379044035822029246823483754854602215035869280453855199171915302879406862793807947285344105991067005185493038370882005106069286893165426035453262949739088328689761676541415552066845538243916687080015277379248062286846119847500455125785281216888979581104100416760176854106890525904804003871967844912776926419778292365918733
k1 = 4961356980843219227031667558158760111429474781353239042846946454889308337426649950562701556812878479419482114480334396560017050901408543482904510839046375272618911899662922000275482705215097956326853000314956770940510205507508883917322367747195211326932972446951696070952604655668087834669239815290687449340666091764203568518066586476150861542456340936303824392273004883320273039066213750777751436497551151274574369325153858390731248298056433816285354182588883715211738843801326831297181947562239993323202961410530072969013398669658073337273085171642258091164822631807295793886169033827781164115751086585872189121242
k2 = 8943660577405892997099415246000964332413663135286363632645590478753346989578467429954062835807609942851365774880023144520942029315601785638267996044694835031239940919206726351387647791985293576677117144309222345482756402074345845506698221273703274410853004407629888264128027446878663894377503365831077629911487977796118893231354280680598325548327444053575447407791091256260091884824630356121390983373431984667887019137026219503921285289004358685317477667095203722657823621429988685962573778350234701781053232256494914398637744373081735647622790113318562356606831868682912936768762749860591989864642992367932846710665
c1 = 4115578106197062017294044310891024039554438131787269391154862526142866937938155870549829472424386226484625850457327387070755337288822640509004443484397234720914851433620556887385729540499953724033259937785600491548446806766462413179765702810698096381537513314758346885921106310631278002150697458246447235914052771405341899822588463120295331632180131956205362147784798497203957828308109092025630961803808101730731656980785388965672073473370194469269645377465298620585379296063436880502566076330461976785816470877632107769103280243111778113065038163250625042092690628478547757779278811188187028242267396799577953511519
c2 = 1069417390392712224013484466911946251479515132512683148923109806683426116132220974153759944203026795479272077929265429391851629949467649257513543604050970026412281764244254971122378729482985044535740328359563865949603944075625096242664299209143911115287867129678168308056632406522013494918385694044348658310785409548526884085469813804712945302487796400392901241763662852123731910949146709219711388725430757562836225353975933990961286601256351973981732004724397292031523206145692402321288085912884435326461626793886145952474077975796841103796283781865005879515976167187625178845457630564285181509041968859289264784559
p = gmpy2.gcd(k1 - 1, n)
flag = (int)(c1 % p)
print(libnum.n2s(flag))
#b'flag{f4eccf2b-19d2-4470-8c1d-d50839cb38c7}'
[祥云杯 2022]little little fermat
考点:费马小定理 rsa yafu分解
解题:
题目:
from Crypto.Util.number import *
from random import *
from libnum import *
import gmpy2
from secret import x
flag = b'?????????'
m = bytes_to_long(flag)
def obfuscate(p, k):
nbit = p.bit_length()
while True:
#getRandomRange是指在-1到1的范围中获取一个数 左闭右开 只可能是-1或0
l1 = [getRandomRange(-1, 1) for _ in '_' * k]
l2 = [getRandomRange(100, nbit) for _ in '_' * k]
l3 = [getRandomRange(10, nbit//4) for _ in '_' * k]
l4 = [getRandomRange(2, 6) for _ in '_' *k]
#sum是求和函数 把列表中的数值加起来
A = sum([l1[_] * 2 ** ((l2[_]+l3[_])//l4[_]) for _ in range(0, k)])
q = p + A
if isPrime(q) * A != 0:
return q
p = getPrime(512)
q = obfuscate(p, 5)
e = 65537
n = p*q
print(f'n = {n}')
assert 114514 ** x % p == 1 # 根据断言语句获得x的值
m = m ^ (x**2)
c = pow(m, e, n)
print(f'c = {c}')
'''
n = 141321067325716426375483506915224930097246865960474155069040176356860707435540270911081589751471783519639996589589495877214497196498978453005154272785048418715013714419926299248566038773669282170912502161620702945933984680880287757862837880474184004082619880793733517191297469980246315623924571332042031367393
c = 81368762831358980348757303940178994718818656679774450300533215016117959412236853310026456227434535301960147956843664862777300751319650636299943068620007067063945453310992828498083556205352025638600643137849563080996797888503027153527315524658003251767187427382796451974118362546507788854349086917112114926883
'''
因为q的生成方式 q和p比较接近 而且512位生成的n比较小
本地测试:
from Crypto.Util.number import getPrime, getRandomRange, isPrime
def obfuscate(p, k):
nbit = p.bit_length()
while True:
#getRandomRange是指在-1到1的范围中获取一个数 左闭右开 只可能是-1或0
l1 = [getRandomRange(-1, 1) for _ in '_' * k]
l2 = [getRandomRange(100, nbit) for _ in '_' * k]
l3 = [getRandomRange(10, nbit//4) for _ in '_' * k]
l4 = [getRandomRange(2, 6) for _ in '_' *k]
#sum是求和函数 把列表中的数值加起来
A = sum([l1[_] * 2 ** ((l2[_]+l3[_])//l4[_]) for _ in range(0, k)])
q = p + A
if isPrime(q) * A != 0:
return q
p = getPrime(512)
q = obfuscate(p, 5)
print(q.bit_length())
#512
利用yafu工具对n进行分解
D:\qdownload\ctf\crypto>yafu-x64 "factor(141321067325716426375483506915224930097246865960474155069040176356860707435540270911081589751471783519639996589589495877214497196498978453005154272785048418715013714419926299248566038773669282170912502161620702945933984680880287757862837880474184004082619880793733517191297469980246315623924571332042031367393)"
fac: factoring 141321067325716426375483506915224930097246865960474155069040176356860707435540270911081589751471783519639996589589495877214497196498978453005154272785048418715013714419926299248566038773669282170912502161620702945933984680880287757862837880474184004082619880793733517191297469980246315623924571332042031367393
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
Total factoring time = 0.5614 seconds
***factors found***
P155 = 11887853772894265642834649929578157180848240939084164222334476057487485972806971092902627112665734648016476153593841839977704512156756634066593725142934001
P155 = 11887853772894265642834649929578157180848240939084164222334476057487485972806971092902627112665734646483980612727952939084061619889139517526028673988305393
ans = 1
得到p和q
p = 11887853772894265642834649929578157180848240939084164222334476057487485972806971092902627112665734648016476153593841839977704512156756634066593725142934001
q = 11887853772894265642834649929578157180848240939084164222334476057487485972806971092902627112665734646483980612727952939084061619889139517526028673988305393
注意嗷!断言语句就是提示!!!
assert 114514 ** x % p == 1 # 根据断言语句获得x的值
这是一个数114514的x次方模p等于1
肯定联想到费马小定理
根据其公式
x = p-1
m = m ^ (x**2)
c = pow(m, e, n)
print(f'c = {c}')
注意rsa解密得到的m不是最终的m 根据异或运算的可逆性对m再进行一次相同的运算即可
exp:
from Crypto.Util.number import getRandomRange
import gmpy2
import libnum
c = 81368762831358980348757303940178994718818656679774450300533215016117959412236853310026456227434535301960147956843664862777300751319650636299943068620007067063945453310992828498083556205352025638600643137849563080996797888503027153527315524658003251767187427382796451974118362546507788854349086917112114926883
p = 11887853772894265642834649929578157180848240939084164222334476057487485972806971092902627112665734648016476153593841839977704512156756634066593725142934001
q = 11887853772894265642834649929578157180848240939084164222334476057487485972806971092902627112665734646483980612727952939084061619889139517526028673988305393
x = p-1
phi = (p-1)*(q-1)
e = 65537
n = p * q
d = gmpy2.invert(e, phi)
m = pow(c,d,n)
m = (int)(m ^ (x**2))
print(libnum.n2s(m))
#b'flag{I~ju5t_w@nt_30_te11_y0u_how_I_@m_f3ll1ng~}45108#@7++3@79?3328?!!@08#712/+963-60#9-/83#+/1@@=59!/84@?3#4!4=-9542/##'
我是哈皮,祝您每天嗨皮!我们下期再见~