# 虎符杯
# RRSSAA
from Crypto.Util.number import getPrime, inverse, GCD, bytes_to_long | |
from random import randint | |
from secret import hint, flag | |
def seq(r, k): | |
v = [r, 2] | |
for i in range(1, k): | |
v = [r * v[0] - v[1], v[0]] | |
ret = v[0] if k != 0 else v[1] | |
return ret | |
def encrypt(m, e, n): | |
while True: | |
r = randint(1, n - 1) | |
if r != 2 and r != n - 2 and GCD(r, n) == 1: | |
break | |
v = seq(r, e) | |
print(r) | |
return ((1 + m * n) * v) % n ** 2 | |
def go(beta, msg): | |
nbits = 1024 | |
delta = 0.63 | |
p = getPrime(nbits // 2) | |
q = next_prime(p + (1 << int(nbits * beta))) | |
n = p * q | |
phi = (p ** 2 - 1) * (q ** 2 - 1) | |
while True: | |
d = getPrime(int(nbits * delta)) | |
if GCD(d, phi) == 1: | |
e = inverse(d, phi) | |
if GCD(e, phi) == 1: | |
break | |
m = bytes_to_long(msg) | |
c = int(encrypt(m, e, n)) | |
print(f"n = {n}") | |
print(f"e = {e}") | |
print(f"c = {c}") | |
go(0.33, hint) | |
go(0.44, flag) | |
''' | |
n = 122774778628333786198247673730199699244621671207929503475974934116435291656353398717362903500544713183492877018211738292001516168567879903073296829793548881467270228989482723510323780292947403861546283099122868428902480999485625751961457245487615479377459707992802193391975415447673215862245349068018710525679 | |
e = 7105408692393780974425936359246908629062633111464343215149184058052422839553782885999575538955213539904607968494147112651103116202742324255190616790664935322773999797774246994193641076154786429287567308416036562198486649223818741008968261111017589015617705905631979526370180766874051731174064076871339400470062519500450745667838729104568633808272577378699913068193645578675484681151593983853443489561431176000585296710615726640355782811266099023653898050647891425956485791437516020367967793814415345332943552405865306305448753989707540163585481006631816856260061985275944250758886027672221219132999488907097750048011 | |
c = 2593129589804979134490367446026701647048897831627696427897506570257238733858989741279626614121210703780002736667183915826429635213867589464112850355422817678245007337553349507744893376944140333333044928907283949731124795240808354521353751152149301719465724014407412256933045835977081658410026081895650068864922666975525001601181989114436054060461228877148361720945120260382962899756912493868467226822547185396096960560068874538680230073168773182775945272726468512949751672553541335307512429217493003429882831235199830121519272447634533018024087697385363918421438799206577619692685090186486444886371979602617584956259 | |
n = 59969098213446598961510550233718258878862148298191323654672950330070587404726715299685997489142290693126366408044603303463518341243526241117556011994804902686998166238333549719269703453450958140262475942580009981324936992976252832887660977703209225426388975233018602730303262439218292062822981478737257836581 | |
e = 970698965238639683403205181589498135440069660016843488485401994654202837058754446853559143754852628922125327583411039117445415303888796067576548626904070971514824878024057391507617988385537930417136322298476467215300995795105008488692961624917433064070351961856959734368784774555385603000155569897078026670993484466622344106374637350023474339105113172687604783395923403613555236693496567851779400707953027457705617050061193750124237055690801725151098972239120476113241310088089420901051617493693842562637896252448161948655455277146925913049354086353328749354876619287042077221173795354616472050669799421983520421287 | |
c = 2757297249371055260112176788534868300821961060153993508569437878576838431569949051806118959108641317578931985550844206475198216543139472405873345269094341570473142756599117266569746703013099627523306340748466413993624965897996985230542275127290795414763432332819334757831671028121489964563214463689614865416498886490980692515184662350519034273510244222407505570929178897273048405431658365659592815446583970229985655015539079874797518564867199632672678818617933927005198847206019475149998468493858071672920824599672525667187482558622701227716212254925837398813278836428805193481064316937182435285668656233017810444672 | |
''' |
nextprime x 不大于 1500
所以可以直接爆破
x=1<<1024*0.33 | |
for i in range(1500): | |
y=iroot((x+i)**2+4*n,2)#(x+i)^2+4(x+i)*p+4p^2 | |
while(y[1]): | |
print(i) | |
print(y[0]) | |
break | |
p=(y-x-i)//2 | |
q=n//p | |
#print(p*q==n) |
分解完之后就没有然后了。。。
要求 m 就要求 v
然后我们看这个函数
def seq(r, k): | |
v = [r, 2] | |
for i in range(1, k): | |
v = [r * v[0] - v[1], v[0]] | |
ret = v[0] if k != 0 else v[1] | |
return ret |
那不就是求通项嘛
然后翻看 la 佬博客看到了矩阵快速幂 但是不会用 啊 die
学习一下. 矩阵快速幂
于是这个 seq 函数又可以写成
def seq(r,k): | |
A=matrix(Zmod(n*n),[r,-1][1,0]) | |
x=matrix(Zmod(n*n),[2],[r]) | |
return int((A**k*x)[0,0]) |
我们可以发现转为矩阵后
seq(seq(r,e),e^{-1})=r\quad mod\quad n^
而
所以
代码
from Crypto.Util.number import inverse, long_to_bytes | |
p = 7743971733771153102128801312798743998017713722732925283466018690899116898707556486947918196848489007935614742583856884731087798825462330340492923214926391 | |
q = 7743971733771153105036156209981171560215008954284943420880584133648389139833517283670475349302080701240378945438911146974137885250527042074631329729385091 | |
n = p * q | |
MOD = n * n | |
phi = (p**2 - 1) * (q**2 - 1) | |
def seq(r, k): | |
A = matrix(Zmod(MOD), [[r, -1], [1, 0]]) | |
x = matrix(Zmod(MOD), [[2], [r]]) | |
return int((A**k * x)[0, 0]) | |
def L(x): | |
return (x % MOD - 1) // n | |
e = 970698965238639683403205181589498135440069660016843488485401994654202837058754446853559143754852628922125327583411039117445415303888796067576548626904070971514824878024057391507617988385537930417136322298476467215300995795105008488692961624917433064070351961856959734368784774555385603000155569897078026670993484466622344106374637350023474339105113172687604783395923403613555236693496567851779400707953027457705617050061193750124237055690801725151098972239120476113241310088089420901051617493693842562637896252448161948655455277146925913049354086353328749354876619287042077221173795354616472050669799421983520421287 | |
c = 2757297249371055260112176788534868300821961060153993508569437878576838431569949051806118959108641317578931985550844206475198216543139472405873345269094341570473142756599117266569746703013099627523306340748466413993624965897996985230542275127290795414763432332819334757831671028121489964563214463689614865416498886490980692515184662350519034273510244222407505570929178897273048405431658365659592815446583970229985655015539079874797518564867199632672678818617933927005198847206019475149998468493858071672920824599672525667187482558622701227716212254925837398813278836428805193481064316937182435285668656233017810444672 | |
d = inverse(e, phi) | |
r = seq(c, d) % n | |
v = seq(r, e) | |
print(long_to_bytes(L(c * inverse(v, MOD)))) |