祥云杯2022
目录
Crypto
tracing
task.py
from secret import p, q, flag
from Crypto.Util.number import bytes_to_long
def gcd(a, b):
s = 0
while b != 0:
print(a, b)
if isOdd(a):
if isOdd(b):
a = a - b
a = rshift1(a)
if a < b:
a, b = b, a
else:
b = rshift1(b)
if a < b:
a, b = b, a
else:
if isOdd(b):
a = rshift1(a)
if a < b:
a, b = b, a
else:
a = rshift1(a)
b = rshift1(b)
s += 1
if s:
return lshift(a, s)
return a
def isOdd(a):
return a & 1 == 1
def rshift1(a):
return a >> 1
def lshift(a, s):
return a << s
n = p * q
e = 65537
phi = (p - 1) * (q - 1)
assert gcd(phi, e) == 1
c = pow(bytes_to_long(flag), e, n)
print(c)
print(n)
根据trace.out逆向得到phi exp.py
import gmpy2
from Crypto.Util.number import long_to_bytes
e = 65537
c = 64885875317556090558238994066256805052213864161514435285748891561779867972960805879348109302233463726130814478875296026610171472811894585459078460333131491392347346367422276701128380739598873156279173639691126814411752657279838804780550186863637510445720206103962994087507407296814662270605713097055799853102
n = 113793513490894881175568252406666081108916791207947545198428641792768110581083359318482355485724476407204679171578376741972958506284872470096498674038813765700336353715590069074081309886710425934960057225969468061891326946398492194812594219890553185043390915509200930203655022420444027841986189782168065174301
a = 1
b = 0
f = open("trace.out","r")
lines = f.readlines()
for i in range(12621):
line = lines[-1-i]
if "a, b = b, a" in line:
a, b = b, a
elif "a = rshift1(a)" in line:
a = a << 1
elif "a = a - b" in line:
a = a + b
elif "b = rshift1(b)" in line:
b = b << 1
else:
continue
# print("phi = ",a)
# print("e = ", b)
phi = 113793513490894881175568252406666081108916791207947545198428641792768110581083359318482355485724476407204679171578376741972958506284872470096498674038813744206060043230633366541996120990867169768523014939944773017185662017479011094588132516102178922759206005551241577259317764398494195585166584573218495824732
e = 65537
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
# flag{a526344-a8c7-411d-bf53-ef6a2479de1a}
Little little fermat
chall.py
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:
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]
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
m = m ^ (x**2)
c = pow(m, e, n)
print(f'c = {c}')
'''
n = 141321067325716426375483506915224930097246865960474155069040176356860707435540270911081589751471783519639996589589495877214497196498978453005154272785048418715013714419926299248566038773669282170912502161620702945933984680880287757862837880474184004082619880793733517191297469980246315623924571332042031367393
c = 81368762831358980348757303940178994718818656679774450300533215016117959412236853310026456227434535301960147956843664862777300751319650636299943068620007067063945453310992828498083556205352025638600643137849563080996797888503027153527315524658003251767187427382796451974118362546507788854349086917112114926883
'''
p和q相差不大,利用平方差遍历求出,factordb也能直接分解n 利用费马小定理求出x=p-1 exp.py
import gmpy2
from Crypto.Util.number import *
e = 65537
n = 141321067325716426375483506915224930097246865960474155069040176356860707435540270911081589751471783519639996589589495877214497196498978453005154272785048418715013714419926299248566038773669282170912502161620702945933984680880287757862837880474184004082619880793733517191297469980246315623924571332042031367393
c = 81368762831358980348757303940178994718818656679774450300533215016117959412236853310026456227434535301960147956843664862777300751319650636299943068620007067063945453310992828498083556205352025638600643137849563080996797888503027153527315524658003251767187427382796451974118362546507788854349086917112114926883
a = gmpy2.iroot(n, 2)[0]
while True:
tmp = pow(a, 2) - n
if gmpy2.is_square(tmp):
b = gmpy2.iroot(tmp, 2)[0]
p = a + b
q = a - b
print(p)
# p = 11887853772894265642834649929578157180848240939084164222334476057487485972806971092902627112665734648016476153593841839977704512156756634066593725142934001
print(q)
# q = 11887853772894265642834649929578157180848240939084164222334476057487485972806971092902627112665734646483980612727952939084061619889139517526028673988305393
break
a += 1
phi = (p-1)*(q-1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
x = p-1
m = m^(x**2)
print(long_to_bytes(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/##'
common_rsa
task.py
from Crypto.Util.number import getPrime, isPrime, bytes_to_long, inverse
from math import lcm
from secret import flag
def gen(g):
bits = 512 - g.bit_length()
while True:
a = getPrime(bits)
p = 2 * a * g + 1
if isPrime(p):
return p
flag = bytes_to_long(flag)
g = getPrime(320)
p = gen(g)
q = gen(g)
n = p * q
d = getPrime(135)
phi = lcm(p - 1, q - 1)
e = inverse(d, phi)
c = pow(flag, e, n)
print("n = {}".format(n))
print("e = {}".format(e))
print("c = {}".format(c))
out.txt
n = 253784908428481171520644795825628119823506176672683456544539675613895749357067944465796492899363087465652749951069021248729871498716450122759675266109104893465718371075137027806815473672093804600537277140261127375373193053173163711234309619016940818893190549811778822641165586070952778825226669497115448984409
e = 31406775715899560162787869974700016947595840438708247549520794775013609818293759112173738791912355029131497095419469938722402909767606953171285102663874040755958087885460234337741136082351825063419747360169129165
c = 97724073843199563126299138557100062208119309614175354104566795999878855851589393774478499956448658027850289531621583268783154684298592331328032682316868391120285515076911892737051842116394165423670275422243894220422196193336551382986699759756232962573336291032572968060586136317901595414796229127047082707519
p-1和q-1都有公因子2g,想到Pollard’s rho algorithm分解n [密码学学习笔记 之 浅析Pollard’s rho algorithm及其应用 | Van1sh的小屋 (jayxv.github.io)](https://jayxv.github.io/2019/11/11/密码学学习笔记之浅析Pollard’s rho algorithm及其应用/) 跟羊城杯2021easy_rsa类似 2021羊城杯比赛复现(Crypto) - 01am - 博客园 (cnblogs.com) 但本题g有192位,用以上脚本跑不出来,放弃 factordb能直接分解n,得到p和q
import gmpy2
from Crypto.Util.number import *
n = 253784908428481171520644795825628119823506176672683456544539675613895749357067944465796492899363087465652749951069021248729871498716450122759675266109104893465718371075137027806815473672093804600537277140261127375373193053173163711234309619016940818893190549811778822641165586070952778825226669497115448984409
e = 31406775715899560162787869974700016947595840438708247549520794775013609818293759112173738791912355029131497095419469938722402909767606953171285102663874040755958087885460234337741136082351825063419747360169129165
c = 97724073843199563126299138557100062208119309614175354104566795999878855851589393774478499956448658027850289531621583268783154684298592331328032682316868391120285515076911892737051842116394165423670275422243894220422196193336551382986699759756232962573336291032572968060586136317901595414796229127047082707519
p = 12080882567944886195662683183857831401912219793942363508618874146487305963367052958581455858853815047725621294573192117155851621711189262024616044496656907
q = n//p
d = gmpy2.invert(e,(p-1)*(q-1))
m = pow(c,d,n)
print(long_to_bytes(m))
# b'flag{9aecf8d8-6966-4ffa-96b0-2e744d28baf2}'
fill
chall.py
from Crypto.Util.number import *
from random import *
from gmpy2 import gcd
from numpy import dot
nbits = 32
msg = getRandomNBitInteger(nbits)
flag = b'flag{sha256(msg)}'
tmp_m = bin(msg)[2:]
f_list = []
for i in range(len(tmp_m)):
f_list.append(int(tmp_m[i]))
r_list =[randint(20, 50)]
for i in range(nbits - 1):
r_list.append(randint(2 * r_list[-1], 3 * r_list[-1]))
while True:
A = randint(2 * r_list[-1] + 1, 3 * r_list[-1])
B = randint(2 * r_list[-1] + 1, 3 * r_list[-1])
if gcd(A, B) == 1:
break
M = [A * x % B for x in r_list]
S = dot(f_list, M)
print(S)
seed = getRandomNBitInteger(30)
s = [0] * nbits
s[0] = seed
m = getRandomNBitInteger(20)
c = getPrime(24)
n = 991125622
for i in range(1, nbits):
s[i] = (s[i-1]*m+c)%n
print(s[0], s[1], s[2])
for t in range(nbits):
M[t] = M[t] + s[t]
print(M)
'''
492226042629702
562734112 859151551 741682801
M = [19621141192340, 39617541681643, 3004946591889, 6231471734951, 3703341368174, 48859912097514, 4386411556216, 11028070476391, 18637548953150, 29985057892414, 20689980879644, 20060557946852, 46908191806199, 8849137870273, 28637782510640, 35930273563752, 20695924342882, 36660291028583, 10923264012354, 29810154308143, 4444597606142, 31802472725414, 23368528779283, 15179021971456, 34642073901253, 44824809996134, 31243873675161, 27159321498211, 2220647072602, 20255746235462, 24667528459211, 46916059974372]
'''
Crypto-LCG(线性同余方程) | 此间的少年 (gitee.io) 根据LCG和s[0]、s[1]、s[2]推出乘数m和增量c,进而推出s,得到M S是f_list和M内积,f_list由0和1组成,相对于求M中哪几个数加起来为S