# -*- coding:utf-8 -*-
#Author: Lazzaro
from Crypto.Util.number import getPrime,isPrime
from math import gamma
import random
def nextPrime(n):
n += 2 if n & 1 else 1
while not isPrime(n):
n += 2
return n
def getNewPrime():
A = getPrime(512)
B = nextPrime(A - random.randint(1e4,1e5))
return nextPrime(gamma(B+2)%A)
p = getNewPrime()
q = getNewPrime()
r = getNewPrime()
n = p * q ** 2 * r ** 3
e = 0x10001
c = pow(flag,e,n)
#pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
#pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
#qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
#qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
#n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
#c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374
hint1:注意伽马函数Γ(x)和阶乘x!的关系式
已知伽马函数Γ(x)和阶乘x!的关系式为Γ(x)=(x-1)!
hint2:威尔逊定理
当p为素数的时候:
(p-1)! -1 mod p
(p-2)! 1 mod p
打开代码,研究了半天才搞清楚下面给的pA,pB是什么意思:p是由getNewPrime这个函数的来的,本来以为这个函数里面的A,B两个随机数是需要爆破或者用什么其他手段来解题,这个pA和pB原来就是这里的A,B,直接把AB给出来了,那就成了求解nextPrime(gamma(B+2)%A),这样就能求出来p,同理得到q,由于nextPrime很明显能看出来是求gamma(B+2)%A的值的下一个素数,那么得到gamma(B+2)%A就能得到p,由此问题就转化成了求解gamma(B+2)%A。
要求解gamma(B+2)%A,就要合理利用已知条件,求解p的时候,利用pA和pB,
求解gamma(pB+2)%pA:
gmma(pB+2)%pA = (pB+1)!%pA
我们想求解(pB+1)!%A,但是(pB+1)太长了,不可能算的出来,看到模A,我们想到威尔逊定理
(pA-2)!1 mod pA,我们想办法把(pB+1)带进去,令x=(pA-2)! / (pB+1)! ,y= (pB+1)!,则该式可以写作 x*y1 mod pA,其中y为x模pA的逆元,则求解y%pA即为求解 : (x的逆元) mod pA
为什么要令 x = (pA-2)! / (pB+1)! ,y= (pB+1)! 呢,因为pA与pB相差很小,且pA>pB,他们的阶乘作除,
即 (pA-2)! / (pB+1)! ,这个数比较好算,因为(pA-2)除以(pB+1)的余数是一个非常小的数,即x是一个非常小的数,求阶乘就是一个再简单不过的事情了!
举个简单的例子:5*4*3*2*1/3*2*1=5*4, 5*4*3*2*1的计算相对麻烦一些,而5*4就很好计算了。
上代码:
from Crypto.Util.number import getPrime,isPrime,inverse,long_to_bytes
from gmpy2 import iroot,mpz
from math import gamma
import random
def nextPrime(n):
n += 2 if n & 1 else 1
while not isPrime(n):
n += 2
return n
e = 0x10001
pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374
p=1
t=(pA-2)%(pB+1)
#print(max)
for i in range(0,t):
p=p*inverse(pA-2-i,pA)%pA
p=nextPrime(p)
#print(p)
q=1
t=(qA-2)%(qB+1)
for i in range(0,t):
q=q*inverse(qA-2-i,qA)%qA
q=nextPrime(q)
#print(q)
r = iroot(n//(p*q*q),3)[0]
#print(r)
phi=(p-1)*(q**2-q)*(r**3-r**2)
d=inverse(e,phi)
m=pow(c,d,n)
m=long_to_bytes(m)
print(m)
有个有趣的地方,之前有个定性思维一直以为n的欧拉函数就是(p-1)*(q-1)
实际上若N是质数p的k次幂(即N=p^k),φ(n)=p^k-p^(k-1)=(p-1)p^(k-1)。
flag{N0w_U_knOw_how_70_u5E_W1lS0n'5_Th30r3m~}