Chenghao Chen | 2022.6
Shanghai University
实际上是一个引言,并且介绍了 ancient 神必编码
Encrypt(k, m)
Decrypt(k, c)
Encode(m)
Decode(e)
实用编码方法:
' '
-> %20
玩具编码方法:
(一种比较古老的题目)
🤔 锟斤拷
> '�'.encode('utf-8')
b'\xef\xbf\xbd'
> '锟斤拷'.encode('gbk')
b'\xef\xbf\xbd\xef\xbf\xbd'
base64
'A-Za-z0-9+/'
)🤔1个ASCII编码字符 8 bit,base64 一个码字 6 bit
如何编码?
'0'
字符填充@Utils.print_params
def encode_b64_with_ascii_bin(text: str):
binary_text = ' '.join(format(ord(char), '08b') for char in text)
encoded_text = base64.b64encode(text.encode('ascii'))
return binary_text, encoded_text
>>> encode_b64_with_ascii_bin('1')
Result: ('00110001', b'MQ==')
>>> encode_b64_with_ascii_bin('12')
Result: ('00110001 00110010', b'MTI=')
>>> encode_b64_with_ascii_bin('123')
Result: ('00110001 00110010 00110011', b'MTIz')
00110001
001100 01
001100 010000
MQ==
00110001 00110010
001100 010011 0010
001100 010011 001000
MTI=
中科院少年班招生要求:手撕大素数分解
textbook RSA,但不会
安全的单向陷门函数
利用Hash的构造……
↑ 在CTF中不是很重要
关注点:
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from gmpy2 import invert
p = getPrime(128)
q = getPrime(128)
n = p * q
phi_n = (p - 1) * (q - 1)
e = 65537
d = invert(e, phi_n)
m = bytes_to_long(b'Hello, world!')
c = pow(m, e, n)
print(long_to_bytes(c))
m_ = pow(c, d, n)
print(long_to_bytes(m_))
n = p * q
phi_n = (p - 1) * (q - 1)
c = pow(m, e, n)
m_ = pow(c, d, n)
Euler 定理:若$m$ 和$n$ 互素,则$m^{\varphi(n)}\equiv 1 (\bmod n)$
$n = pq, m < p, m < q$
$m^{ed} \bmod n = (m \bmod n) (1)^k \bmod n$
$= m \bmod n$
一种显然的攻击方法
工具:
from Crypto.Util.number import getPrime, bytes_to_long
from secret import flag
p = getPrime(128); q = getPrime(128)
n = p * q; phi_n = (p - 1) * (q - 1)
e = 65537
m = bytes_to_long(flag)
c = pow(m, e, n)
print(e); print(n); print(c)
# 65537
# 60312637199635801058227385421553206347253918440828187249920737695124886809487
# 14673748133379805475254231366717984351237192567008318062632171353909225806981
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from gmpy2 import invert
e = 65537
n = 60312637199635801058227385421553206347253918440828187249920737695124886809487
c = 14673748133379805475254231366717984351237192567008318062632171353909225806981
p = 197_171715_027747_339553_722339_715394_949697
q = 305_888890_762796_266901_267235_667077_573071
phi_n = (p - 1) * (q - 1)
d = invert(e, phi_n)
m = pow(c, d, n)
print(long_to_bytes(m)) # b'flag{waaaaa!}'
攻击方法:Brute-force $k$
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from gmpy2 import invert
from secret import flag
p = getPrime(1024); q = getPrime(1024)
n = p * q
phi_n = (p - 1) * (q - 1)
e = 3
m = bytes_to_long(flag)
c = pow(m, e, n)
print(n) # 26904410424513850825570476100349039892015194282487533873593315635034916011599061467392303815306522302238291633926964464814719214360401710146660376698471334910919067631926359580676153648632072950953163800307452838629641502897202385008108650370210545081025594811346683868462241559023145711983469942804412184091372375410284776347467254451154229882893062676381167273759770532779269018405250741326382414128740659109901734318180074363144722523208937640098203271310259652100969148051051093951864097917984729026851490884006661280087277384483099665162338506927680335934552565079554069982479529726554065109787187999302935991923
print(c) # 31850476042869993856571693940454371912053546150176657900652418191965217904787395659877
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from gmpy2 import invert, iroot
e = 3
n = 26904410424513850825570476100349039892015194282487533873593315635034916011599061467392303815306522302238291633926964464814719214360401710146660376698471334910919067631926359580676153648632072950953163800307452838629641502897202385008108650370210545081025594811346683868462241559023145711983469942804412184091372375410284776347467254451154229882893062676381167273759770532779269018405250741326382414128740659109901734318180074363144722523208937640098203271310259652100969148051051093951864097917984729026851490884006661280087277384483099665162338506927680335934552565079554069982479529726554065109787187999302935991923
c = 31850476042869993856571693940454371912053546150176657900652418191965217904787395659877
i = 0
while True:
res = iroot(c+i*n, 3)
if (res[1] == True):
m = res[0]
break
print(f'\r i = {i}', end='')
i += 1
print(long_to_bytes(m)) # b'flag{yeahh!}'
为什么 $n$ 每次都要重新生成?
假设重复利用 $n$
攻击利用扩展 Euclidean算法($ae_1+be_2\equiv1 (\bmod n)$)
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from gmpy2 import invert
from secret import flag
p = getPrime(1024); q = getPrime(1024)
n = p * q; phi_n = (p - 1) * (q - 1)
e1 = getPrime(64); e2 = getPrime(64)
m = bytes_to_long(flag)
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
print(n) # 15170797923892054990521305052012509493080568087081023750033741867542316768999951573646413753990834682138025772136109204509899638782616660243658254139599441045875522966283555995043016187825383943336990507193641549144516174056706810327582160942467845635495500282175716057977476074952304306822781341844677001797438535701007875365722512160465708455832225273446521621543823855283418665848061608565467010656663089973001969597624553258295614154262448569387247406903093192587512853122780974388687415079948784446715412138463084264315211437439421528085827503277507203193141860916227982534613135645331857382065795066181077972687
print(e1) # 9576072468337167131
print(e2) # 14939113163917820627
print(c1) # 2513254454937818539320001229715025367247490957880668052989469295768681316833496719591412918630312453676811713071414028525870397074185767769616621123070069290764497635067026772298781749325373581840750494743329569059911576372085939972798876709058137797441729480657418587957036217376669515209286767084322875440709473172117549721159755662718590954657925357615152141194701388245440956597032994743626281679318033304014413523468865879100948882376690862202243813943679264465530741774092309002963261692618613612757084511814696332961571153968794051052454203918248339932068292297123047852899029619284314623645966095118119009347
print(c2) # 111884194864476659139117439739496481475155670608279036093048194153438641356919888323493937575276768933859172174857427366301659912545016807339447507119749910478246208487569012877733924932126136220607107687643614867740936831894203006503190514539481184016080767542829000468460046831987529804871513461035761669072519101709086162745537847204230913330316446448321633091235409913844098851446548290633634428674269538902219278990312260703412892258533797387149328008600614619162876396153768090553946757954666629947494973412821804101257176286021758524844324847062425088549302146311886502815379004832574784487510491117203079999
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from gmpy2 import invert, gcdext
n = 15170797923892054990521305052012509493080568087081023750033741867542316768999951573646413753990834682138025772136109204509899638782616660243658254139599441045875522966283555995043016187825383943336990507193641549144516174056706810327582160942467845635495500282175716057977476074952304306822781341844677001797438535701007875365722512160465708455832225273446521621543823855283418665848061608565467010656663089973001969597624553258295614154262448569387247406903093192587512853122780974388687415079948784446715412138463084264315211437439421528085827503277507203193141860916227982534613135645331857382065795066181077972687
e1 = 9576072468337167131
e2 = 14939113163917820627
c1 = 2513254454937818539320001229715025367247490957880668052989469295768681316833496719591412918630312453676811713071414028525870397074185767769616621123070069290764497635067026772298781749325373581840750494743329569059911576372085939972798876709058137797441729480657418587957036217376669515209286767084322875440709473172117549721159755662718590954657925357615152141194701388245440956597032994743626281679318033304014413523468865879100948882376690862202243813943679264465530741774092309002963261692618613612757084511814696332961571153968794051052454203918248339932068292297123047852899029619284314623645966095118119009347
c2 = 111884194864476659139117439739496481475155670608279036093048194153438641356919888323493937575276768933859172174857427366301659912545016807339447507119749910478246208487569012877733924932126136220607107687643614867740936831894203006503190514539481184016080767542829000468460046831987529804871513461035761669072519101709086162745537847204230913330316446448321633091235409913844098851446548290633634428674269538902219278990312260703412892258533797387149328008600614619162876396153768090553946757954666629947494973412821804101257176286021758524844324847062425088549302146311886502815379004832574784487510491117203079999
gcd, a, b = gcdext(e1, e2)
m = pow(c1, a, n) * pow(c2, b, n) % n
print(long_to_bytes(m)) # b'flag{zzZzzz}'
n=111579281253062835933426384911624147476643761873859056052262953708472502295896995336206948247132120107672205900512683609160859648751240065855474276219994138942756004010593263891617114133265991974868701112328627021663637323794664244913574481420588357101626589818721266368311914527609221633764177929512932572431
c=88870500129800281970105647465034249962408043895876390636948381637648563368839286409491487914616157808689098599152353765340352358559100732226540197353569675894540877184980032542071641988321773490955995436271805369857124988164094166523947397743529988209384145974211768757896487704118410946032129361588104389830
e=65537
import gmpy2
from sympy import nextprime
from Crypto.Util.number import *
n=111579281253062835933426384911624147476643761873859056052262953708472502295896995336206948247132120107672205900512683609160859648751240065855474276219994138942756004010593263891617114133265991974868701112328627021663637323794664244913574481420588357101626589818721266368311914527609221633764177929512932572431
c=88870500129800281970105647465034249962408043895876390636948381637648563368839286409491487914616157808689098599152353765340352358559100732226540197353569675894540877184980032542071641988321773490955995436271805369857124988164094166523947397743529988209384145974211768757896487704118410946032129361588104389830
e=65537
q=nextprime(gmpy2.iroot(n,2)[0])
p=n//q
d=gmpy2.invert(e,(p-1)*(q-1))
m=pow(c,d,n)
print(long_to_bytes(m))
#flag{llsajdjlksajldjsdjkl}
Wiener’s Theorem
RSA:
n=56661243519426563299920058134092862370737397949947210394843021856477420959615132553610830104961645574615005956183703191006421508461009698780382360943562001485153455401650697532951591191737164547520951628336941289873198979641173541232117518791706826699650307105202062429672725308809988269372149027026719779368169
e=36269788044703267426177340992826172140174404390577736281478891381612294207666891529019937732720246602062358244751177942289155662197410594434293004130952671354973700999803850153697545606312859272554835232089533366743867361181786472126124169787094837977468259794816050397735724313560434944684790818009385459207329
c=137954301101369152742229874240507191901061563449586247819350394387527789763579249250710679911626270895090455502283455665178389917777053863730286065809459077858674885530015624798882224173066151402222862023045940035652321621761390317038440821354117827990307003831352154618952447402389360183594248381165728338233
BASE:
"GHI45FQRSCX****UVWJK67DELMNOPAB3"
上强度
'flag{[0-9A-Za-z=_]*}'
新佛曰:諸隸僧降冥吽諸陀摩隸僧缽冥薩願耨咤陀
願羅咤喃迦祗蜜耨阿嚤僧喼所聞薩闍嚩聞念須亦心
耨冥心阿冥聞慧蜜咤冥心念訶冥嚩冥聞冥念降咤冥
劫耨降寂願慧般祗闍隸冥修阿闍莊陀冥莊冥劫莊嚴
冥宣隸阿摩嚩蜜心咒冥闍我須咒慧冥闍諦羅迦聞慧
婆劫嘚慧咒迦慧慧我慧冥闍念劫嘇隸蜜祗伏嚤慧咒
修缽聞色祗冥闍僧嘚迦降阿莊冥慧聞蜜降咤寂波嘇
塞薩如囑
'flag{[0-9A-Za-z=_]*}'
from Crypto.Util.number import getPrime, bytes_to_long
from gmpy2 import is_prime, invert
from typing import Tuple
from secert import flag
def gen_rsa_param() -> Tuple[int, int, int, int, int]: ...
def rsa_encrypt(m: str, *args) -> str: ...
params = gen_rsa_param()
print(rsa_encrypt(flag, *params))
print(params[2])
# 5796768148637887491255587039409951397511832995737366433505141785703232675749200657380232851343254281355390391562734825283953711907092653161783752372166386
# 7948512242985881433771203281939490726039994357587772712416312873824297606161653053722572268861029945737411249803561023517431875922105282741637330609169129