题目:
class Key:
PRIVATE_INFO = ['P', 'Q', 'D', 'DmP1', 'DmQ1']
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
assert self.bits % 8 == 0
def ispub(self):
return all(not hasattr(self, key) for key in self.PRIVATE_INFO)
def ispriv(self):
return all(hasattr(self, key) for key in self.PRIVATE_INFO)
def pub(self):
p = deepcopy(self)
for key in self.PRIVATE_INFO:
if hasattr(p, key):
delattr(p, key)
return p
def priv(self):
raise NotImplementedError()
def genkey(bits):
assert bits % 2 == 0
while True:
p = genprime(bits // 2)
q = genprime(bits // 2)
e = 65537
d, _, g = egcd(e, (p-1) * (q-1))
if g != 1: continue
iQmP, iPmQ, _ = egcd(q, p)
return Key(
N=p*q, P=p, Q=q, E=e, D=d%((p-1)*(q-1)), DmP1=d%(p-1), DmQ1=d%(q-1),
iQmP=iQmP%p, iPmQ=iPmQ%q, bits=bits,
)
def encrypt(key, data):
data = bytes2num(pad(data, key.bits))
assert 0 <= data and data < key.N
data = pow(data, key.E, key.N)
return num2bytes(data, key.bits // 8)
def decrypt(key, data):
assert key.ispriv() and len(data) * 8 == key.bits
data = bytes2num(data)
assert 0 <= data and data < key.N
v1 = pow(data, key.DmP1, key.P)
v2 = pow(data, key.DmQ1, key.Q)
data = (v2 * key.P * key.iPmQ + v1 * key.Q * key.iQmP) % key.N
return unpad(num2bytes(data, key.bits // 8))
给出变量 i p m d , i q m p , e , ϕ ( n ) , c ipmd,iqmp,e,\phi(n),c ipmd,iqmp,e,ϕ(n),c
注意到ipmq,iqmp,_=egcd(p,q)
,得到
i p m q ⋅ p ≡ 1 ( m o d q ) i q m p ⋅ q ≡ 1 ( m o d p ) ipmq\cdot p\equiv1(\bmod q)\\iqmp\cdot q\equiv1(\bmod p) ipmq⋅p≡1(modq)iqmp⋅q≡1(modp)
目标是推出p,q
{ i p m q ⋅ p = k 1 ⋅ q + 1 i q m p ⋅ q = k 2 ⋅ p + 1 \begin{cases}ipmq\cdot p=k_1\cdot q+1\\iqmp\cdot q=k_2\cdot p+1\end{cases} {ipmq⋅p=k1⋅q+1iqmp⋅q=k2⋅p+1
两式相加得
∵ i p m q ⋅ p ⋅ i q m p ⋅ q = k 1 ⋅ q ⋅ k 2 ⋅ p + k 1 ⋅ q + k 2 ⋅ p + 1 \because ipmq\cdot p\cdot iqmp\cdot q=k_1\cdot q\cdot k_2\cdot p+k_1\cdot q+k_2\cdot p+1 ∵ipmq⋅p⋅iqmp⋅q=k1⋅q⋅k2⋅p+k1⋅q+k2⋅p+1
∴ ( i p m q ⋅ i q m p − k 1 ⋅ k 2 ) ⋅ n = k 1 ⋅ q + k 2 ⋅ p + 1 \therefore (ipmq\cdot iqmp-k_1\cdot k_2)\cdot n=k_1\cdot q +k_2\cdot p+1 ∴(ipmq⋅iqmp−k1⋅k2)⋅n=k1⋅q+k2⋅p+1
再注意iqmp=iqmp%p,ipmq=ipmq%q
{ i q m p ≤ p i p m q ≥ q ⟶ { 0 ≤ k 1 < p 0 ≤ k 2 < q \begin{cases}iqmp\leq p\\ipmq\geq q\end{cases}\longrightarrow\begin{cases}0\leq k_1 {iqmp≤pipmq≥q⟶{0≤k1<p0≤k2<q
取 k 1 , k 2 k_1,k_2 k1,k2为右极限,带入前式右边
( i p m q ⋅ i q m p − k 1 ⋅ k 2 ) ⋅ n < 2 n + 1 (ipmq\cdot iqmp-k_1\cdot k_2)\cdot n<2n+1 (ipmq⋅iqmp−k1⋅k2)⋅n<2n+1
所以 ( i p m q ⋅ i q m p − k 1 ⋅ k 2 ) ⋅ n (ipmq\cdot iqmp-k_1\cdot k_2)\cdot n (ipmq⋅iqmp−k1⋅k2)⋅n只能1 or 2
为2时,右边 k 1 , k 2 k_1,k_2 k1,k2必须取p,q,不可能。于是,只能为1
所以 n = k 1 ⋅ q + k 2 ⋅ p + 1 n=k_1\cdot q+k_2\cdot p+1 n=k1⋅q+k2⋅p+1
由3,4两相加得 i p m q ⋅ p + i q m p ⋅ q = k 1 ⋅ q + k 2 ⋅ p + 2 = n + 1 ipmq\cdot p+iqmp\cdot q=k_1\cdot q+k_2\cdot p+2=n+1 ipmq⋅p+iqmp⋅q=k1⋅q+k2⋅p+2=n+1
又 ϕ ( n ) = ( p − 1 ) ⋅ ( q − 1 ) = n − ( q + p ) + 1 \phi(n)=(p-1)\cdot(q-1)=n-(q+p)+1 ϕ(n)=(p−1)⋅(q−1)=n−(q+p)+1
列出方程组
{ i p m q ⋅ p + i q m p ⋅ q = n + 1 ϕ ( n ) = n − ( p + q ) + 1 ϕ ( n ) = ( p − 1 ) ⋅ ( q − 1 ) \begin{cases}ipmq\cdot p+iqmp\cdot q=n+1\\\phi(n)=n-(p+q)+1\\\phi(n)=(p-1)\cdot(q-1)\end{cases} ⎩⎪⎨⎪⎧ipmq⋅p+iqmp⋅q=n+1ϕ(n)=n−(p+q)+1ϕ(n)=(p−1)⋅(q−1)
三个未知数,n,p,q
,三条方程,可解
用z3跑一下就好
Exp:
from z3 import *
import gmpy2
from Crypto.Util.number import long_to_bytes
q=Int("q")
p=Int("p")
n=Int("n")
phi = 11177929896833318778267064419554047209804133035532602158237892469506082395935495256139136112194510151728917586404919115707761109072628761295860181662822356164160284726297946695851442119129722147684494637497443200139538149832495961915450185804086755272971387407998204100589137627495400914243828434106078332327997903842841517071021248147779935078071506489655500155896938283840729728572328660647233974344849571246788826036265850539775145330135792207209473452843737567371694666658091855216070403504619639510901644370971614286091867701992201923071041178318790575030522483839410855929335515391080189720203086802888683798400
iqmp = 91015809392527255523072044687980286577671138545257803641612547883387289541035388722157767029686572001797549231630088970758132893695316792508265294751302240594796242084165161239587935396541914404832318478070695600559420277875549100164011180835754613742632525637982101603421982448705454195363628987806367263766
ipmq = 10870198964186987138989651624057552405853366954080463316431710442091837631287759912193054100505356356476481503550009625275319473929512195371174525538642232600176213853601253377888749818545192155785873323173291991086758912490744417777560275318548708479769299122462125768416235737869558154549710389717852257846
s=Solver()
s.add(iqmp*q+ipmq*p==n+1)
s.add(phi==(p-1)*(q-1))
s.add(phi==n-(q+p)+1)
s.check()
#print(s.model())
p = 100920329311023043792405408005417242117374946885462223687244834540168939266980874513828622981269823935831791149302266474816959342903482904850705622841034674617774508046423149433115499066314613920674997684075319293745518393044329170181630440249931588961323218471139932722932324367911140345310018504720309693151
q = 110759942750329561983364096770824818957156636845110590823134362698749612147788955083351174879972411435569300696393151260960779092387966200431706198509584768247841937719219850118991339268977853455607397866025870712323459278215127588375709815956587698977630219989552045686550681692693762584298742938231996726337
c = 0x3ce4e91042f61e3b03537d825e7619a02b3f729a91e2de4fb724b95cabe8fb2a7a92c4270025d93aed94f1726ca761083328a7784806e1467f0bc204ef95484ce6b0d207574c6dba4fa91664db4c787e3df517bcfc370a0c5eed8a70b45be8d1e757a9d40eb410e66d2110ac9ece435f76d71e134e2bdbe565e8853e1100ae276211c2b9c49219bca8805ff697dcf84be00b071c3be01f35ba9a4ea1d8ef2c69044982a7fc021d2f6f93b8755948a606a8a376e74d995f439aeeb844ecf678a189916adca406197a1d2eaf2abe84ae6e794560537bcde43a1504f135874d5de9e0a2d95093e4ba7a87641e769e46a911c94ff60525b21c9c709068a89808b6bf
e=65537
d=gmpy2.invert(e,phi)
m=gmpy2.powmod(c,d,p*q)
print(long_to_bytes(m))
Flag:fductf{b97ba9e174d916d30609a6e8b3d78ca3}
题目:
import sympy
import random
def myGetPrime():
A= getPrime(513)
print(A)
B=A-random.randint(1e3,1e5)
print(B)
return sympy.nextPrime((B!)%A)
p=myGetPrime()
#A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
#B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
q=myGetPrime()
#A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
#B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
r=myGetPrime()
n=p*q*r
#n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
c=pow(flag,e,n)
#e=0x1001
#c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428
#so,what is the flag?
注意的事B!
不是什么运算,是表示b的阶乘
威尔逊定理 ( p − 1 ) ! ≡ − 1 m o d p (p-1)!\equiv-1\bmod p (p−1)!≡−1modp
关键步骤就是运用威尔逊定理
b = a − x b=a-x b=a−x
( a − x ) ! ⋅ ( a − x + 1 ) ⋅ ( a − x + 2 ) ⋅ … ( a − 1 ) ≡ − 1 m o d a (a-x)!\cdot(a-x+1)\cdot(a-x+2)\cdot…(a-1)\equiv-1\bmod a (a−x)!⋅(a−x+1)⋅(a−x+2)⋅…(a−1)≡−1moda
连乘b+1到a-1为止,并求逆。得到-b!,b!=a-b!
Exp:
import gmpy2
from Crypto.Util.number import long_to_bytes
A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
e=0x1001
c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428
def wilison(b,a):
p=1
b=b+1
while b<a:
p*=b
p%=a
b+=1
return a-p
p=gmpy2.next_prime(gmpy2.invert(wilison(B1,A1),A1))
q=gmpy2.next_prime(gmpy2.invert(wilison(B2,A2),A2))
r=n//q//p
phi=(p-1)*(q-1)*(r-1)
d=gmpy2.invert(e,phi)
m=gmpy2.powmod(c,d,n)
print(long_to_bytes(m))
题目:
from random import choice
from Crypto.Util.number import isPrime, sieve_base as primes
from flag import flag
def getPrime(bits):
while True:
n = 2
while n.bit_length() < bits:
n *= choice(primes)
if isPrime(n + 1):
return n + 1
e = 0x10001
m = int.from_bytes(flag.encode(), 'big')
p, q = [getPrime(2048) for _ in range(2)]
n = p * q
c = pow(m, e, n)
# n = 32849718197337581823002243717057659218502519004386996660885100592872201948834155543125924395614928962750579667346279456710633774501407292473006312537723894221717638059058796679686953564471994009285384798450493756900459225040360430847240975678450171551048783818642467506711424027848778367427338647282428667393241157151675410661015044633282064056800913282016363415202171926089293431012379261585078566301060173689328363696699811123592090204578098276704877408688525618732848817623879899628629300385790344366046641825507767709276622692835393219811283244303899850483748651722336996164724553364097066493953127153066970594638491950199605713033004684970381605908909693802373826516622872100822213645899846325022476318425889580091613323747640467299866189070780620292627043349618839126919699862580579994887507733838561768581933029077488033326056066378869170169389819542928899483936705521710423905128732013121538495096959944889076705471928490092476616709838980562233255542325528398956185421193665359897664110835645928646616337700617883946369110702443135980068553511927115723157704586595844927607636003501038871748639417378062348085980873502535098755568810971926925447913858894180171498580131088992227637341857123607600275137768132347158657063692388249513
# c = 26308018356739853895382240109968894175166731283702927002165268998773708335216338997058314157717147131083296551313334042509806229853341488461087009955203854253313827608275460592785607739091992591431080342664081962030557042784864074533380701014585315663218783130162376176094773010478159362434331787279303302718098735574605469803801873109982473258207444342330633191849040553550708886593340770753064322410889048135425025715982196600650740987076486540674090923181664281515197679745907830107684777248532278645343716263686014941081417914622724906314960249945105011301731247324601620886782967217339340393853616450077105125391982689986178342417223392217085276465471102737594719932347242482670320801063191869471318313514407997326350065187904154229557706351355052446027159972546737213451422978211055778164578782156428466626894026103053360431281644645515155471301826844754338802352846095293421718249819728205538534652212984831283642472071669494851823123552827380737798609829706225744376667082534026874483482483127491533474306552210039386256062116345785870668331513725792053302188276682550672663353937781055621860101624242216671635824311412793495965628876036344731733142759495348248970313655381407241457118743532311394697763283681852908564387282605279108%
先讲非预期解
从加密过程中素数生成中可以看出p,q
应该很接近,此时可以尝试yafu分解大素数
但是命令行模式下无法输入太长,我们新建一个n.txt
,在里面写入n的值,注意最后要加换行!然后用在命令行用命令yafu-x64.exe "factor(@)" -batchfile n.txt
。然后几秒钟后就得到了pq的值。
出题人想法:
http://www.soreatu.com/ctf/writeups/Writeup%20for%20Crypto%20problems%20in%20NCTF%202019.html#childrsa
题目:
#!/usr/bin/python
from Crypto.Util.number import *
from secret import flag, n, t, z
def encrypt_time_capsule(msg, n, t, z):
m = bytes_to_long(msg)
l = pow(2, pow(2, t), n)
c = l ^ z ^ m
return (c, n, t, z)
print encrypt_time_capsule(flag, n, t, z)
主要问题是pow(2,t)
,t过大,要运算时间过长
需要用到欧拉定理
∵ 2 2 t ≡ l m o d n 2 e ≡ l m o d n ∴ e ≡ 2 t m o d ϕ ( n ) \because2^{2^t}\equiv l\bmod n\\\quad 2^e\ \equiv l\bmod n\\\therefore e\equiv 2^t\bmod \phi(n) ∵22t≡lmodn2e ≡lmodn∴e≡2tmodϕ(n)
l=pow(2,pow(2,pow(2,t,phi(n)),n))
就是解题的关键了
from functools import reduce
from Crypto.Util.number import *
n = 16801166465109052984956796702219479136700692152603640001472470493600002617002298302681832215942994746974878002533318970006820414971818787350153626339308150944829424332670924459749331062287393811934457789103209090873472485865328414154574392274611574654819495894137917800304580119452390318440601827273834522783696472257727329819952363099498446006266115011271978143149347765073211516486037823196033938908784720042927986421555211961923200006343296692217770693318701970436618066568854673260978968978974409802211538011638213976732286150311971354861300195440286582255769421094876667270445809991401456443444265323573485901383
factors = [15013, 583343756982313, 585503197547927, 609245815680559, 612567235432583, 634947980859229, 635224892351513, 639438000563939, 654170414254271, 654269804672441, 667954470985657, 706144068530309, 721443717105973, 737993471695639, 744872496387077, 746232585529679, 795581973851653, 815694637597057, 817224718609627, 841183196554507, 864339847436159, 873021823131881, 884236929660113, 899583643974479, 922745965897867, 942872831732189, 951697329369323, 971274523714349, 1017566110290559, 1018452110902339, 1025985735184171, 1027313536626551, 1059774237802229, 1067609726096989, 1070689247726159, 1079289330417443, 1098516592571807, 1107673252158281, 1108654254305327, 1110918654474373, 1111516996694389, 1112193819715441]
phi = reduce(lambda curr, p: curr*(p-1), factors, 1)
test_n = reduce(lambda curr, p: curr*p, factors, 1)
assert test_n == n
assert pow(2, phi, n) == 1
c = 30263951492003430418944035844723976843761515320480688994488846431636782360488888188067655841720110193942081554547272176290791213962513701884837856823209432209367951673301622535940395295826053396595886942990258678430777333636450042181585837395671842878310404080487115827773100028876775230121509570227303374672524063165714509957850966189605469484201028704363052317830254920108664916139026741331552127849056897534960886647382429202269846392809641322613341548025760209280611758326300214885296175538901366986310471066687700879304860668964595202268317011117634615297226602309205086105573924029744405559823548638486054634428
t = 6039738711082505929
z = 13991757597132156574040593242062545731003627107933800388678432418251474177745394167528325524552592875014173967690166427876430087295180152485599151947856471802414472083299904768768434074446565880773029215057131908495627123103779932128807797869164409662146821626628200600678966223382354752280901657213357146668056525234446747959642220954294230018094612469738051942026463767172625588865125393400027831917763819584423585903587577154729283694206436985549513217882666427997109549686825235958909428605247221998366006018410026392446064720747424287400728961283471932279824049509228058334419865822774654587977497006575152095818
e = pow(2, t, phi)
l=pow(2,e,n)
m=l^z^c
print(long_to_bytes(m))
其他题目之后再补充……
之后更新在我的blog
https://www.cnblogs.com/militray-axe/