-
-
[推荐][原创]CTF-RSA常见题型、思路及解法
-
2020-10-29 18:07 17142
-
RSA入门:
写在前面:
这篇文章是帮助对RSA不熟悉的朋友且需要较为快速、深入的了解RSA而写的
不涉及非常晦涩难懂的数学知识和算法(不过最简单的原理说明还是有的)
攻击方法也是最容易遇到的(RSA的进阶篇除外)
并且所有的例题都是比较新的,甚至还有刚刚结束的比赛的题目
基本原理:
公钥与私钥的产生:
(1)进行加密之前,首先找出2个不同的大质数p和q
(2)计算n=p*q
(3)根据欧拉函数,求得φ(n)=φ(p)φ(q)=(p−1)(q−1)
(4)找出一个公钥e,e要满足: 1<e<φ(n) 的整数,且使e和φ(N)互质。
(5)根据e*d除以φ(n)余数为1,找到私钥d。
(6)所以,公钥就是(n,e) 私钥就是(n,d)
消息加密:
m^e除以n求余数即为c(密文)
消息解密:
c^d除以n求余数即为m(明文)
关于基本原理的一些说明:
算法原理:
RSA公开密钥密码体制的原理是:
根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥
模运算规则:
模运算与基本四则运算有些相似,但是除法例外。其规则如下:
- (a + b) % p = (a % p + b % p) % p
- (a - b) % p = (a % p - b % p) % p
- (a * b) % p = (a % p * b % p) % p
- (a ^ b) % p = ((a % p)^b) % p
结合律:
- ((a+b) % p + c) % p = (a + (b+c) % p) % p (5)
- ((a*b) % p * c)% p = (a *(b*c)%p) % p (6)
交换律:
- (a + b) % p = (b+a) % p
- (a * b) % p = (b * a) % p
分配律:
- ((a +b)% p * c) % p = ((a * c) %p + (b * c) % p) % p
重要定理:
- 若a≡b (% p),则对于任意的c,都有(a + c) ≡ (b + c) (%p)
- 若a≡b (% p),则对于任意的正整数c,都有(a * c) ≡ (b * c) (%p)
- 若a≡b (% p),c≡d (% p),则 (a + c) ≡ (b + d) (%p),(a - c) ≡ (b - d) (%p),
(a * c) ≡ (b * d) (%p)
欧拉函数:
定义:
在数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(因此φ(1)=1)
例如φ(8)= 4,因为1,3,5,7均和8互质
特殊性质:
- p^k型欧拉函数:
若N是质数p的k次幂(即N=p^k),φ(n)=p^k-p^(k-1)=(p-1)p^(k-1)。
- mn型欧拉函数(联想rsa算法的p和q)
设n为正整数,以φ(n)表示不超过n且与n互素的正整数的个数,称为n的欧拉函数值。
若m,n互质,φ(mn)=(m-1)(n-1)=φ(m)φ(n)。
基础知识的练习:
buuctf-RSA:
在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17
求解出d作为flag提交
1 2 3 4 5 6 7 8 | #!/usr/bin/python import gmpy2 #导入gmpy2库,gmpy2库在rsa解密过程中有很大的作用 p = 473398607161 q = 4511491 e = 17 phi = (q - 1 ) * (p - 1 ) #φ(n)通常也被写作phi d = gmpy2.invert(e,phi) #通过e和phi求d print (d) |
buuctf-rsarsa:
题目:
1 2 3 4 5 6 7 8 | Math is cool! Use the RSA algorithm to decode the secret message, c, p, q, and e are parameters for the RSA algorithm. p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483 q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407 e = 65537 c = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034 Use RSA to find the secret message |
解题:
1 2 3 4 5 6 7 8 9 10 11 12 | #!/usr/bin/python import gmpy2 p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483 q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407 e = 65537 c = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034 n = q * p phi = (q - 1 ) * (p - 1 ) d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) print (m) |
倒数第二行的gmpy2.powmod也可以用pow函数替代,不过前者比后者的计算速度快很多,之后有道题可以体现出来
RSA的基础攻击方式:
自此,我们已经了解了rsa的原理,现在开始进入学习rsa的一些攻击方式
1.暴力分解n
用于已知e,c,m,不是很大的n(小于等于1024),或者n具有缺陷,q和p相差过大或过小
常用分解方法:
名称 | 特点 | 个人使用感受 |
---|---|---|
factordb n(需要安装对应的py模块,pip install factordb-pycli) | 利用数据库查询 | 可以查询到大多数数据,非常推荐 |
yafu分解 | 可以对有缺陷的n快速分解 | 有时候factordb查询不到时可以用yafu分解试试,可能有奇效 |
linux下命令行: factor n(计算,n较小时推荐) | 环境依赖少 | 应该是爆破计算,对于大数支持很差 |
在线分解: http://factordb.com/ | 数据库查询 | 体验不佳 |
如果第一项,和第二项都无法分解,就应该考虑换一种思路了,题目考点应该不是暴力分解
例题1:
已知一段RSA加密的信息为:0xdc2eeeb2782c且已知加密所用的公钥:
(N=322831561921859 e = 23)
请解密出明文,提交时请将数字转化为ascii码提交
比如你解出的明文是0x6162,那么请提交字符串ab
提交格式:PCTF{明文字符串}
解题:
首先整理一下已知条件:
我们已知公钥:
n和e,以及密文c
想要通过密文c来解得明文m需要私钥d
而私钥d需要通过e和phi求出,其中e已知,所以我们只需要知道phi
而phi = (q-1) * (p-1),幸运的是我们知道n = q*p,且q和p都是素数,如果我们能通过n分解出p和q则可以解出这道题目了
分解n:
1 | factordb n |
得到p = 13574881 , q = 23781539(q和p不涉及其他关系时,p和q的顺序无所谓)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/usr/bin/python from Crypto.Util.number import long_to_bytes import gmpy2 p = 13574881 q = 23781539 n = q * p e = 23 c = 0xdc2eeeb2782c phi = (q - 1 ) * (p - 1 ) d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) m = long_to_bytes(m) #把整数依照asc码转化成字符串 print (m) |
例题2:[GWCTF 2019]BabyRSA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import hashlib import sympy from Crypto.Util.number import * flag = 'GWHT{******}' secret = '******' assert ( len (flag) = = 38 ) half = len (flag) / 2 flag1 = flag[:half] flag2 = flag[half:] secret_num = getPrime( 1024 ) * bytes_to_long(secret) p = sympy.nextprime(secret_num) q = sympy.nextprime(p) N = p * q e = 0x10001 F1 = bytes_to_long(flag1) F2 = bytes_to_long(flag2) c1 = F1 + F2 c2 = pow (F1, 3 ) + pow (F2, 3 ) assert (c2 < N) m1 = pow (c1, e, N) m2 = pow (c2, e, N) output = open ( 'secret' , 'w' ) output.write( 'N=' + str (N) + '\n' ) output.write( 'm1=' + str (m1) + '\n' ) output.write( 'm2=' + str (m2) + '\n' ) output.close() |
可以从这两句代码看出:
1 2 | p = sympy.nextprime(secret_num) q = sympy.nextprime(p) |
可以知道,q和p相差很小,所以这个n是具有缺陷的,通常有两种攻击方式
- 对n开方并把值设为r,那么q < r < p ,且q和p是素数,既然p和q相差很小,可以通过循环快速可以确定p和q
- yafu分解
分解出来后,是一个简单是数学等式,用z3约束器可以快速求解
(使用yafu分解的攻击方法比较简单,这里就不写了)
解题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import isPrime,long_to_bytes from z3 import * N = 636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163 e = 65537 cc1 = 90009974341452243216986938028371257528604943208941176518717463554774967878152694586469377765296113165659498726012712288670458884373971419842750929287658640266219686646956929872115782173093979742958745121671928568709468526098715927189829600497283118051641107305128852697032053368115181216069626606165503465125725204875578701237789292966211824002761481815276666236869005129138862782476859103086726091860497614883282949955023222414333243193268564781621699870412557822404381213804026685831221430728290755597819259339616650158674713248841654338515199405532003173732520457813901170264713085107077001478083341339002069870585378257051150217511755761491021553239 cc2 = 487443985757405173426628188375657117604235507936967522993257972108872283698305238454465723214226871414276788912058186197039821242912736742824080627680971802511206914394672159240206910735850651999316100014691067295708138639363203596244693995562780286637116394738250774129759021080197323724805414668042318806010652814405078769738548913675466181551005527065309515364950610137206393257148357659666687091662749848560225453826362271704292692847596339533229088038820532086109421158575841077601268713175097874083536249006018948789413238783922845633494023608865256071962856581229890043896939025613600564283391329331452199062858930374565991634191495137939574539546 r = gmpy2.iroot(N, 2 )[ 0 ] for i in range (r,N): if isPrime(i): if N % i = = 0 : p = i q = N / / i break phi = (p - 1 ) * (q - 1 ) d = gmpy2.invert(e,phi) a = gmpy2.powmod(cc1,d,N) b = gmpy2.powmod(cc2,d,N) #a = 2732509502629189160482346120094198557857912754 #b = 5514544075236012543362261483183657422998274674127032311399076783844902086865451355210243586349132992563718009577051164928513093068525554 s = Solver() c1, c2 = Ints( 'c1 c2' ) s.add(c1 + c2 = = 2732509502629189160482346120094198557857912754 ) s.add(c1 * * 3 + c2 * * 3 = = 5514544075236012543362261483183657422998274674127032311399076783844902086865451355210243586349132992563718009577051164928513093068525554 ) if s.check() = = sat: m1 = (s.model()[c1]).as_long() m2 = (s.model()[c2]).as_long() m1 = str (long_to_bytes(m1))[ 2 : - 1 ] m2 = str (long_to_bytes(m2))[ 2 : - 1 ] m = m1 + m2 print (m) |
2.与公钥私钥交互获得数据:
工具 | 优点 | 缺点 |
---|---|---|
openssl | 功能最全 | 对数据要求严格 |
RsaCtfTool | 操作简单 | 功能不全 |
Python | 功能灵活 | 需要自己写脚本 |
openssl:
指令 | 功能 |
---|---|
genrsa | 生成并输入一个RSA私钥 |
rsa | 处理RSA密钥的格式转换等问题 |
rsautl | 使用RSA密钥进行加密、解密、签名和验证等运算 |
genrsa
1 2 | usage: genrsa [args] [numbits] / / 密钥位数,建议 1024 及以上 - out file output the key to file / / 生成的密钥文件,可从中提取公钥 |
rsa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | rsa [options] <infile >outfile - inform arg input format - one of DER NET PEM / / 输入文件格式,默认pem格式 - outform arg output format - one of DER NET PEM / / 输入文件格式,默认pem格式 - in arg input file / / 输入文件 - passin arg input file pass phrase source / / 指定输入文件的加密口令,可来自文件、终端、环境变量等 - out arg output file / / 输出文件 - passout arg output file pass phrase source / / 指定输出文件的加密口令,可来自文件、终端、环境变量等 - des encrypt PEM output with cbc des / / 使用des加密输出的文件 - des3 encrypt PEM output with ede cbc des using 168 bit key / / 使用des3加密输出的文件 - seed encrypt PEM output with cbc seed / / 使用seed加密输出的文件 - aes128, - aes192, - aes256 encrypt PEM output with cbc aes / / 使用aes加密输出的文件 - camellia128, - camellia192, - camellia256 encrypt PEM output with cbc camellia / / 使用camellia加密输出的文件呢 - text print the key in text / / 以明文形式输出各个参数值 - noout don't print key out / / 不输出密钥到任何文件 - modulus print the RSA key modulus / / 输出模数指 - check verify key consistency / / 检查输入密钥的正确性和一致性 - pubin expect a public key in input file / / 指定输入文件是公钥 - pubout output a public key / / 指定输出文件是公钥 - engine e use engine e, possibly a hardware device. / / 指定三方加密库或者硬件 |
rsautl
数据补齐方式 | 输入数据长度 | 输出数据长度 | 参数字符串 |
---|---|---|---|
PKCS#1 v1.5 | 少于(密钥长度-11)字节 | 同密钥长度 | -pkcs |
PKCS#1 OAEP | 少于(密钥长度-11)字节 | 同密钥长度 | -oaep |
PKCS#1 for SSLv23 | 少于(密钥长度-11)字节 | 同密钥长度 | -ssl |
不使用补齐 | 同密钥长度 | 同密钥长度 | -raw |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Usage: rsautl [options] - in file input file / / 输入文件 - out file output file / / 输出文件 - inkey file input key / / 输入的密钥 - keyform arg private key format - default PEM / / 指定密钥格式 - pubin input is an RSA public / / 指定输入的是RSA公钥 - certin input is a certificate carrying an RSA public key / / 指定输入的是证书文件 - ssl use SSL v2 padding / / 使用SSLv23的填充方式 - raw use no padding / / 不进行填充 - pkcs use PKCS #1 v1.5 padding (default) //使用V1.5的填充方式 - oaep use PKCS #1 OAEP //使用OAEP的填充方式 - sign sign with private key / / 使用私钥做签名 - verify verify with public key / / 使用公钥认证签名 - encrypt encrypt with public key / / 使用公钥加密 - decrypt decrypt with private key / / 使用私钥解密 - hexdump hex dump output / / 以 16 进制dump输出 - engine e use engine e, possibly a hardware device. / / 指定三方库或者硬件设备 - passin arg pass phrase source / / 指定输入的密码 |
生成私钥:
openssl genrsa -out prikey
查看私钥:
openssl rsa -in prikey -text -modulus
从私钥总提取公钥:
openssl rsa -in prikey -pubout -out pubkey
查看公钥:
openssl rsa -in pubkey -text -modulus -pubin
加密:
openssl rsautl -encrypt -in filename -inkey pubkey -pubin -out filename
解密:(如果有对应的补齐方式需要指定)
rsautl -decrypt -inkey prikey -in filename
Rsactftool:
1 2 3 4 5 6 7 | usage: RsaCtfTool.py [ - h] [ - - publickey PUBLICKEY] [ - - timeout TIMEOUT] [ - - createpub] [ - - dumpkey] [ - - ext] [ - - uncipherfile UNCIPHERFILE] [ - - uncipher UNCIPHER] [ - - verbosity {CRITICAL,ERROR,WARNING,DEBUG,INFO}] [ - - private] [ - - ecmdigits ECMDIGITS] [ - n N] [ - p P] [ - q Q] [ - e E] [ - - key KEY] [ - - attack ] |
生成公钥:
RsaCtfTool.py --createpub -n number -e number > pubkey
查看公钥:
RsaCtfTool.py --dumpkey --filename pub.pem
已知公钥求私钥:
RsaCtfTool.py --publickey pubkey --private
已知公钥,自动解密:
RsaCtfTool.py --publickey pubkey --uncipherfile filename
例题1.西湖论剑-rsa
给了两个文件,message 和 public.key
以及加密脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP from secret import flag import os rsa = RSA.generate( 2048 ) public_key = rsa.publickey().exportKey() f = open ( "public.key" , "w" ) f.write(public_key.decode()) f.close() rsakey = RSA.importKey( open ( "public.key" , "r" ).read()) rsa = PKCS1_OAEP.new(rsakey) msg = rsa.encrypt(flag.encode()) f = open ( "message" , "wb" ) f.write(msg) f.close() |
首先打开公钥看看
1 | openssl rsa - in public.key - pubin - modulus - text |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | Modulus: 00 :c2: 07 : 45 : 22 : 3f :f5:b9: 4b : 2c :d8: 41 : 21 : 66 :f7: 28 : 8a : 21 :f2: 18 : 7e : 1a : 42 : 14 : 53 : 91 : 8c :ab: 03 :c8: 02 : 53 : 45 : 12 : 33 :eb: 1b :dc: 23 : 63 : 74 : 42 : 28 :aa: 86 : 94 :a8:c2:cb:c8: 33 :f8: 0d :df: 40 : 83 : 1a : 68 : 90 : 1b : 23 : 0b : 83 :f3:f0:fe:d4:b7: 2d : 0b : 94 : 2b : 5e : 95 :de: da:c8:dc:c0: 04 : 7a : 2a :fb: 90 :c8: 1e :d7: 2d : 3a :d4: 9b : 72 :fc: 8b :d0:d3: 16 : 7d :dd:aa: 6a :b5: 16 : 7c : 05 : 8d :f3: 6a :f1: 90 :b2: 16 : 08 : 5b :bd: 9d : 62 : 1f : 9b :d2: 3a : 09 : 3e : 4e : 3d : 9c :c3: 87 :b6: 27 : 4f : 2c : 33 : 9c : 88 : e1:b2:d9: 08 :ac:b3: 3f : 4e : 20 :e6: 47 :ab:ee: 07 : 14 : a3:cc:e4: 64 : 6e : 89 : 62 : 94 :b7: 81 : 03 :dc:c9:a4:db: 7e :d6: 81 : 16 : 4c : 6e : 6c :c7:fd: 33 : 47 : 6e : 17 : 4a : 6c : 70 : 70 : 37 :b2: 50 : 49 : 13 : 65 :f9:f0:eb: 76 :ae:ab:a0: 7d :b2:f6: 62 :d8: 80 : 48 :af: 98 :c8: 8c : 76 :c6: 71 : 0d : b9: 65 : 8d : 49 :fc:a0:ca:f1:f5:cd: 99 :dc: 07 :f1: 88 : 43 : 2b : 48 :f8: 55 : 71 : 16 : 8a :d1: 0f :c8: 24 :b7:b6: 82 : ba:d6:ca:a5:d1: 2f :f6:f0: 4c : 92 : 78 : 6b : 73 : 8a :b1: 9b :b7 Exponent: 1d : 2d : 2f : 1f : 17 : 3f : 81 :cf: 36 : 8f :ec: 06 :d4: 0d : 47 : fd: 92 :f8: 61 : 5c : 12 :ee:c1: 41 : 68 :f2: 88 : 42 : 79 : 52 : b8:cf: 5a : 53 : 8f : 70 :ba: 33 : 41 :b6:a1: 73 :ae: 80 : 37 : 5a : 96 :b0:d3: 84 :d9: 72 : 2b : 19 : 14 : 9f : 78 : 94 : 73 : 75 : e0:a3: 3d :f5:e6: 93 :ed:ab:d5:e4:d4: 4c :ff:a9:e5: 25 :ea: 01 : 4f : 3f :a4: 99 :b5:f7:b2: 9b : 21 : 9d : 90 :b8: 8d :a5: 5a :ae: 3a : 08 : 63 : 73 : 38 :d7:be:d0: 56 :e3:ae: c5: 75 :be: 56 :bb:de: 53 : 4b : 35 : 5a : 2e : 77 : 57 :db: 7a : ec:a9: 6e : 78 :d6: 7f : 21 : 53 : 0b : 7c : 3e :c2: 4a :c6: 1f : 9b : 47 : 4a :b2: 83 : 22 : 0d :d9: 54 : 51 : 35 :d0: 65 :a7: 24 : ce: 2f : 8f : 44 :e3: 2e : 46 : 0e :ef: 5f : 99 : 58 : 00 : 9c : 58 : af: 59 : 51 : 93 :d7: 7e : 72 :c2: 5f : 0c :b0: 15 : 05 :b9: 93 : c1: 35 : 32 : 8b : 11 :b5: 00 :dc:ab:c9: 55 :c9: 17 : 7f : 83 : 9d :d0: 43 : 58 : 6e : 25 :a3: 13 : 35 :e7:d5: 43 : 7d :c9:e6: cd: 6d : 4e :be:cb: 29 : 37 :e1: 60 : 26 :c2: 79 : 2e : 17 : 45 : f4: 4e :ed: 54 : 11 :be:aa:b5: 5e :d0: 90 : 5d :b9: 19 : 8c : bd: 43 : 11 : 11 :be: 87 : 46 : 2f : 46 : 36 : 9e : 31 :d1:a4: 61 : 3f |
可以看到e和n非常大,应该考虑Wiener攻击(后面会介绍到)
不过这里主要是介绍和公钥、私钥的交互
所以我们用RsaCtfTool来爆破出私钥
1 | python RsaCtfTool.py - - publickey public.key - - private >> pri.key |
得到了私钥,尝试用openssl解密
1 | openssl rsautl - decrypt - in message - inkey pri.key |
却报错了,为什么呢
我们观察题目给出的加密脚本第二行"from Crypto.Cipher import PKCS1_OAEP"
说明这里是用的使用OAEP的填充方式,而解密是也必须指明对应的填充模式
1 | openssl rsautl - decrypt - oaep - in message - inkey pri.key |
3.简单的数学变换
例题1:[GUET-CTF2019]BabyRSA
1 2 3 4 5 | p + q : 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea (p + 1 )(q + 1 ) : 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740 e : 0xe6b1bee47bd63f615c7d0a43c529d219 d : 0x2dde7fbaed477f6d62838d55b0d0964868cf6efb2c282a5f13e6008ce7317a24cb57aec49ef0d738919f47cdcd9677cd52ac2293ec5938aa198f962678b5cd0da344453f521a69b2ac03647cdd8339f4e38cec452d54e60698833d67f9315c02ddaa4c79ebaa902c605d7bda32ce970541b2d9a17d62b52df813b2fb0c5ab1a5 enc_flag : 0x50ae00623211ba6089ddfae21e204ab616f6c9d294e913550af3d66e85d0c0693ed53ed55c46d8cca1d7c2ad44839030df26b70f22a8567171a759b76fe5f07b3c5a6ec89117ed0a36c0950956b9cde880c575737f779143f921d745ac3bb0e379c05d9a3cc6bf0bea8aa91e4d5e752c7eb46b2e023edbc07d24a7c460a34a9a |
解题:
这类题核心解法大体相同,出题人给出有唯一解的q和p的方程,通过解出q,p来解题
大多数简单的数学方程可以用z3约束器快速解出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import long_to_bytes from z3 import * tmp1 = 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea tmp2 = 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740 e = 0xe6b1bee47bd63f615c7d0a43c529d219 d = 0x2dde7fbaed477f6d62838d55b0d0964868cf6efb2c282a5f13e6008ce7317a24cb57aec49ef0d738919f47cdcd9677cd52ac2293ec5938aa198f962678b5cd0da344453f521a69b2ac03647cdd8339f4e38cec452d54e60698833d67f9315c02ddaa4c79ebaa902c605d7bda32ce970541b2d9a17d62b52df813b2fb0c5ab1a5 c = 0x50ae00623211ba6089ddfae21e204ab616f6c9d294e913550af3d66e85d0c0693ed53ed55c46d8cca1d7c2ad44839030df26b70f22a8567171a759b76fe5f07b3c5a6ec89117ed0a36c0950956b9cde880c575737f779143f921d745ac3bb0e379c05d9a3cc6bf0bea8aa91e4d5e752c7eb46b2e023edbc07d24a7c460a34a9a s = Solver() p,q = Ints( 'p q' ) s.add(p + q = = tmp1) s.add((p + 1 ) * (q + 1 ) = = tmp2) assert s.check() = = sat p = s.model()[p].as_long() q = s.model()[q].as_long() n = q * p phi = (p - 1 ) * (q - 1 ) d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) print (long_to_bytes(m)) |
例题2.[BJDCTF2020]easyrsa
题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from Crypto.Util.number import getPrime,bytes_to_long from sympy import Derivative from fractions import Fraction from secret import flag p = getPrime( 1024 ) q = getPrime( 1024 ) e = 65537 n = p * q z = Fraction( 1 ,Derivative(arctan(p),p)) - Fraction( 1 ,Derivative(arth(q),q)) m = bytes_to_long(flag) c = pow (m,e,n) print (c,z,n) ''' output: 7922547866857761459807491502654216283012776177789511549350672958101810281348402284098310147796549430689253803510994877420135537268549410652654479620858691324110367182025648788407041599943091386227543182157746202947099572389676084392706406084307657000104665696654409155006313203957292885743791715198781974205578654792123191584957665293208390453748369182333152809882312453359706147808198922916762773721726681588977103877454119043744889164529383188077499194932909643918696646876907327364751380953182517883134591810800848971719184808713694342985458103006676013451912221080252735948993692674899399826084848622145815461035 32115748677623209667471622872185275070257924766015020072805267359839059393284316595882933372289732127274076434587519333300142473010344694803885168557548801202495933226215437763329280242113556524498457559562872900811602056944423967403777623306961880757613246328729616643032628964072931272085866928045973799374711846825157781056965164178505232524245809179235607571567174228822561697888645968559343608375331988097157145264357626738141646556353500994924115875748198318036296898604097000938272195903056733565880150540275369239637793975923329598716003350308259321436752579291000355560431542229699759955141152914708362494482 15310745161336895413406690009324766200789179248896951942047235448901612351128459309145825547569298479821101249094161867207686537607047447968708758990950136380924747359052570549594098569970632854351825950729752563502284849263730127586382522703959893392329333760927637353052250274195821469023401443841395096410231843592101426591882573405934188675124326997277775238287928403743324297705151732524641213516306585297722190780088180705070359469719869343939106529204798285957516860774384001892777525916167743272419958572055332232056095979448155082465977781482598371994798871917514767508394730447974770329967681767625495394441 ''' |
解题:
这道题挺有意思的,在给出的脚本第10行
有两个没见过的函数,通过搜索资料,可以查到相关资料
- Fraction,返回参数1/参数2的分数形式
Derivative,返回参数1函数在参数2点的导数
联系这两点
可以知道
z = Fraction(1,Derivative(arctan(p),p))-Fraction(1,Derivative(arth(q),q))
= 1/(1/(1+p^2)) - 1/(1/(1-q^2))
= 1+p^2 + q^2 -1
= p^2 + q^2
又把本题转化成简单的数学问题了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import long_to_bytes from z3 import * c = 7922547866857761459807491502654216283012776177789511549350672958101810281348402284098310147796549430689253803510994877420135537268549410652654479620858691324110367182025648788407041599943091386227543182157746202947099572389676084392706406084307657000104665696654409155006313203957292885743791715198781974205578654792123191584957665293208390453748369182333152809882312453359706147808198922916762773721726681588977103877454119043744889164529383188077499194932909643918696646876907327364751380953182517883134591810800848971719184808713694342985458103006676013451912221080252735948993692674899399826084848622145815461035 z = 32115748677623209667471622872185275070257924766015020072805267359839059393284316595882933372289732127274076434587519333300142473010344694803885168557548801202495933226215437763329280242113556524498457559562872900811602056944423967403777623306961880757613246328729616643032628964072931272085866928045973799374711846825157781056965164178505232524245809179235607571567174228822561697888645968559343608375331988097157145264357626738141646556353500994924115875748198318036296898604097000938272195903056733565880150540275369239637793975923329598716003350308259321436752579291000355560431542229699759955141152914708362494482 n = 15310745161336895413406690009324766200789179248896951942047235448901612351128459309145825547569298479821101249094161867207686537607047447968708758990950136380924747359052570549594098569970632854351825950729752563502284849263730127586382522703959893392329333760927637353052250274195821469023401443841395096410231843592101426591882573405934188675124326997277775238287928403743324297705151732524641213516306585297722190780088180705070359469719869343939106529204798285957516860774384001892777525916167743272419958572055332232056095979448155082465977781482598371994798871917514767508394730447974770329967681767625495394441 e = 65537 s = Solver() a,b = Ints( 'a b' ) s.add( a * b = = 15310745161336895413406690009324766200789179248896951942047235448901612351128459309145825547569298479821101249094161867207686537607047447968708758990950136380924747359052570549594098569970632854351825950729752563502284849263730127586382522703959893392329333760927637353052250274195821469023401443841395096410231843592101426591882573405934188675124326997277775238287928403743324297705151732524641213516306585297722190780088180705070359469719869343939106529204798285957516860774384001892777525916167743272419958572055332232056095979448155082465977781482598371994798871917514767508394730447974770329967681767625495394441 ) s.add( a * * 2 + b * * 2 = = 32115748677623209667471622872185275070257924766015020072805267359839059393284316595882933372289732127274076434587519333300142473010344694803885168557548801202495933226215437763329280242113556524498457559562872900811602056944423967403777623306961880757613246328729616643032628964072931272085866928045973799374711846825157781056965164178505232524245809179235607571567174228822561697888645968559343608375331988097157145264357626738141646556353500994924115875748198318036296898604097000938272195903056733565880150540275369239637793975923329598716003350308259321436752579291000355560431542229699759955141152914708362494482 ) s.add( 0 < a, 0 < b) if s.check() = = sat: q = s.model()[a].as_long() p = s.model()[b].as_long() phi = (q - 1 ) * (p - 1 ) d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) print (long_to_bytes(m)) |
常见攻击方式:
1.低加密指数分解攻击
原理:
在 RSA 中 e 也称为加密指数。由于 e 是可以随意选取的,选取小一点的 e 可以缩短加密时间(比如 e=2,e=3),但是选取不当的话,就会造成安全问题
由于e很小,当n很大时,m^e也比n小很多.尝试把c开根号看能否得到明文.
例题:[NCTF2019]easyRSA
题目描述:
When you need really secure communications, you use RSA with a 4096 bit key.
I want really really really secure communications to transmit the nuclear launch codes (yeah IoT is everywhere man) so I used RSA with a 16777216 bit key. Surely russians will not be able to factor that one !
File md5 : 1049a0c83a2e34760363b4ad9778753f
解题:
题目给出了n和c,e,不过这个文本文件的大小高达7.4m,要是常规分解的话,估计量子计算机也够呛
不过由于n是16777216 bit的数字,e只有0x10001,所以m^e << n,符合低加密指数分解攻击的条件
1 2 3 4 5 6 7 8 9 10 11 12 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import long_to_bytes e = 0x10001 f = open ( "./out.txt" , "r" ) data = f.read() data = int (data, 16 ) m = gmpy2.iroot(data,e)[ 0 ] print (long_to_bytes(m)) |
这里我们也应该理解到,低加密指数并非指e == 2或e == 3这类,e的数值很小,而是m^e和n的相对大小
2.小明文攻击
原理:
公钥e很小,明文m也不大的话,于是m^e=k*n+m 中的的k值很小甚至为0(k==0时,和上一种攻击方式差别不大),爆破k或直接开e次方即可。
例题:[De1CTF2019]babyrsa(部分)
1 2 3 4 5 6 7 8 9 | from data import e1,e2,p,q1p,q1q,hint,flag ee1 = 42 ee2 = 3 ce1 = 45722651786340123946960815003059322528810481841378247280642868553607692149509126962872583037142461398806689489141741494974836882341505234255325683219092163052843461632338442529011502378931140356111756932712822516814023166068902569458299933391973504078898958921809723346229893913662577294963528318424676803942288386430172430880307619748186863890050113934573820505570928109017842647598266634344447182347849367714564686341871007505886728393751147033556889217604647355628557502208364412269944908011305064122941446516990168924709684092200183860653173856272384 ce2 = 13908468332333567158469136439932325992349696889129103935400760239319454409539725389747059213835238373047899198211128689374049729578146875309231962936554403287882999967840346216695208424582739777034261079550395918048421086843927009452479936045850799096750074359160775182238980989229190157551197830879877097703347301072427149474991803868325769967332356950863518504965486565464059770451458557744949735282131727956056279292800694203866167270268988437389945703117070604488999247750139568614939965885211276821987586882908159585863514561191905040244967655444219603287214405014887994238259270716355378069726760953320025828158 tmp = 864078778078609835167779565982540757684070450697854309005171742813414963447462554999012718960925081621571487444725528982424037419052194840720949809891134854871222612682162490991065015935449289960707882463387 n = 15911581555796798614711625288508309704791837516232122410440958830726078821069050404012820896260071751380436992710638364294658173571101596931605797509712839622479368850251206419748090059752427303611760004621378226431226983665746837779056271530181865648115862947527212787824629516204832313026456390047768174765687040950636530480549014401279054346098030395100387004111574278813749630986724706263655166289586230453975953773791945408589484679371854113457758157492241225180907090235116325034822993748409011554673180494306003272836905082473475046277554085737627846557240367696214081276345071055578169299060706794192776825039 assert ( pow (e1,ee1,n) = = ce1) #断言,括号里的等式恒成立 assert ( pow (e2 + tmp,ee2,n) = = ce2) |
解题:
我们拿到两个类似rsa加密的式子:
- (e1^ee1) mod n == ce1
- ((e2+tmp)^ee2) mod n == ce2
由于两个式子的加密指数很小(ee1 = 42,ee2 = 3),考虑小指数攻击
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #!/usr/bin/python import gmpy2 ee1 = 42 ee2 = 3 ce1 = 45722651786340123946960815003059322528810481841378247280642868553607692149509126962872583037142461398806689489141741494974836882341505234255325683219092163052843461632338442529011502378931140356111756932712822516814023166068902569458299933391973504078898958921809723346229893913662577294963528318424676803942288386430172430880307619748186863890050113934573820505570928109017842647598266634344447182347849367714564686341871007505886728393751147033556889217604647355628557502208364412269944908011305064122941446516990168924709684092200183860653173856272384 ce2 = 13908468332333567158469136439932325992349696889129103935400760239319454409539725389747059213835238373047899198211128689374049729578146875309231962936554403287882999967840346216695208424582739777034261079550395918048421086843927009452479936045850799096750074359160775182238980989229190157551197830879877097703347301072427149474991803868325769967332356950863518504965486565464059770451458557744949735282131727956056279292800694203866167270268988437389945703117070604488999247750139568614939965885211276821987586882908159585863514561191905040244967655444219603287214405014887994238259270716355378069726760953320025828158 n = 15911581555796798614711625288508309704791837516232122410440958830726078821069050404012820896260071751380436992710638364294658173571101596931605797509712839622479368850251206419748090059752427303611760004621378226431226983665746837779056271530181865648115862947527212787824629516204832313026456390047768174765687040950636530480549014401279054346098030395100387004111574278813749630986724706263655166289586230453975953773791945408589484679371854113457758157492241225180907090235116325034822993748409011554673180494306003272836905082473475046277554085737627846557240367696214081276345071055578169299060706794192776825039 tmp = 864078778078609835167779565982540757684070450697854309005171742813414963447462554999012718960925081621571487444725528982424037419052194840720949809891134854871222612682162490991065015935449289960707882463387 #--------find e1-------- for k in range ( 200000000 ): c = k * n + ce1 if gmpy2.iroot(c,ee1)[ 1 ]: e1 = gmpy2.iroot(c,ee1)[ 0 ] break #---------check e1----- if ce1 = = gmpy2.powmod(e1,ee1,n): print ( "e1 = %d" % e1) #--------find e2-------- for k in range ( 1000000 ): c = k * n + ce2 if gmpy2.iroot(c, 3 )[ 1 ]: m = gmpy2.iroot(c, 3 )[ 0 ] e2 = m - tmp break #---------check e2----- if ce2 = = gmpy2.powmod((e2 + tmp), 3 ,n): print ( "e2 = %d" % e2) |
1 2 | e1 = 15218928658178 e2 = 381791429275130 |
3.低解密指数攻击:
本质上,第一种、第二种攻击方式都是因为e选取的较小而造成的缺陷,那么e选取的非常大是不是就很安全呢?
实际上也不是,当e很大时,就会造成d非常的小,也具有相当大的危险
原理:
顾名思义,这是一种针对d很小时的攻击方式
此种攻击方法由Micheal j.Wiener于1989提出,所以也被称为Wiener's attack,该方法基于连分数
该方法在github已有完整可用的代码,之后所有的低解密指数也是利用以上脚本进行的
题目:buuctf-rsa2
1 2 3 4 5 | N = 101991809777553253470276751399264740131157682329252673501792154507006158434432009141995367241962525705950046253400188884658262496534706438791515071885860897552736656899566915731297225817250639873643376310103992170646906557242832893914902053581087502512787303322747780420210884852166586717636559058152544979471 e = 46731919563265721307105180410302518676676135509737992912625092976849075262192092549323082367518264378630543338219025744820916471913696072050291990620486581719410354385121760761374229374847695148230596005409978383369740305816082770283909611956355972181848077519920922059268376958811713365106925235218265173085 import hashlib flag = "flag{" + hashlib.md5( hex (d)).hexdigest() + "}" |
解题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/usr/bin/python2 import gmpy2 from Crypto.PublicKey import RSA import ContinuedFractions, Arithmetic from Crypto.Util.number import long_to_bytes def wiener_hack(e, n): frac = ContinuedFractions.rational_to_contfrac(e, n) convergents = ContinuedFractions.convergents_from_contfrac(frac) for (k, d) in convergents: if k ! = 0 and (e * d - 1 ) % k = = 0 : phi = (e * d - 1 ) / / k s = n - phi + 1 discr = s * s - 4 * n if (discr > = 0 ): t = Arithmetic.is_perfect_square(discr) if t ! = - 1 and (s + t) % 2 = = 0 : print ( "Hacked!" ) return d return False def main(): n = int ( input ( "input the n :\n" )) e = int ( input ( "input the e :\n" )) d = wiener_hack(e, n) print (d) if __name__ = = "__main__" : main() |
4.模不互素
原理:
把大数分解成两个素数很困难,但是求两个大数的公因子很容易
当:
- n1 = a*b
- n2 = a*c
我们可以通过求gcd(n1,n2)来得到a,再通过除法分别求得b和c,从而达到了分解大素数的目的
例题:QCTF2018Xman-RSA(部分)
1 2 3 4 5 6 7 8 9 10 | p1 = get_a_prime( 128 ) p2 = get_a_prime( 128 ) p3 = get_a_prime( 128 ) n1 = p1 * p2 n2 = p1 * p3 e = 0x1001 c1 = encrypt(msg1, e, n1) c2 = encrypt(msg2, e, n2) print (c1) print (c2) |
解题:
可以通过gcd(n1,n2)快速求得p1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import long_to_bytes,isPrime n1 = 2499586809914462821807624371088011200618603528498132509598946284572455726453497171635086810524607288333625665025664872216634366700044105279185519761587818169021167370991396691510275499486673922916370294043072503635630922980240462022218565365191228535222150496387990987123639567257124081274667568443678527637259644488779394704508217357758791670308548246801142468699716221789070607334747835552167450340441488756779323653879402176647890584656379628685893686585469918686253137796663587854943386347039389769790329948165162483370187914412810153613198247569427480466488647563900948387020677830797976534568626241686906738179 n2 = 7741603029707932330739678982394275613217057249691533148704382574439895657047911501600910571360188397109729289277796711334388156202412769743785164713243932001078475541271281825859671767783178037363138683152051263779907568124470598237502689045677891605285193637790880045372303913424654655825837641694318544209980415256180296972066060073206323473960669679401950151966003026531573962072358852304635671658878866030003484715256388556599713638695448516673643703041094737763957937855870992247472296348887788212823714735080211059688680618314050267995177478035769912691185787944037050674163079867101586607780761245261558200843 n3 = 9895571060693703887018268413746107679094703478067972087862851570192520012058188062485476484700707994684397704099884436398099581319015589480235346899990863625919087077906193223937343450727301243043576326163300258770936289423785376338765758863453745278516208013244068358484113062931878984339475569902332075509121153749576470546863477142562563573654198332099438611713385318497180237117792417826080724886477023904678472464557511959911739272258202310963925049222305927992349171516332320267610895787011879250778522843808895509894741144901052000573058315131265960606119769594234837973757057319170067823816025499647517874841 c1 = 0x1240198b148089290e375b999569f0d53c32d356b2e95f5acee070f016b3bef243d0b5e46d9ad7aa7dfe2f21bda920d0ac7ce7b1e48f22b2de410c6f391ce7c4347c65ffc9704ecb3068005e9f35cbbb7b27e0f7a18f4f42ae572d77aaa3ee189418d6a07bab7d93beaa365c98349d8599eb68d21313795f380f05f5b3dfdc6272635ede1f83d308c0fdb2baf444b9ee138132d0d532c3c7e60efb25b9bf9cb62dba9833aa3706344229bd6045f0877661a073b6deef2763452d0ad7ab3404ba494b93fd6dfdf4c28e4fe83a72884a99ddf15ca030ace978f2da87b79b4f504f1d15b5b96c654f6cd5179b72ed5f84d3a16a8f0d5bf6774e7fd98d27bf3c9839 c2 = 0x129d5d4ab3f9e8017d4e6761702467bbeb1b884b6c4f8ff397d078a8c41186a3d52977fa2307d5b6a0ad01fedfc3ba7b70f776ba3790a43444fb954e5afd64b1a3abeb6507cf70a5eb44678a886adf81cb4848a35afb4db7cd7818f566c7e6e2911f5ababdbdd2d4ff9825827e58d48d5466e021a64599b3e867840c07e29582961f81643df07f678a61a9f9027ebd34094e272dfbdc4619fa0ac60f0189af785df77e7ec784e086cf692a7bf7113a7fb8446a65efa8b431c6f72c14bcfa49c9b491fb1d87f2570059e0f13166a85bb555b40549f45f04bc5dbd09d8b858a5382be6497d88197ffb86381085756365bd757ec3cdfa8a77ba1728ec2de596c5ab p1 = gmpy2.gcd(n1,n2) p2 = n1 / / p1 p3 = n2 / / p1 assert isPrime(p1) / / 检查这三个数是否为素数 assert isPrime(p2) assert isPrime(p3) e = 0x1001 phi1 = (p1 - 1 ) * (p2 - 1 ) phi2 = (p1 - 1 ) * (p3 - 1 ) d1 = gmpy2.invert(e,phi1) d2 = gmpy2.invert(e,phi2) m1 = gmpy2.powmod(c1,d1,n1) m2 = gmpy2.powmod(c2,d2,n2) print (long_to_bytes(m1)) print (long_to_bytes(m2)) |
5.共模攻击:
原理:
对同一明文的多次加密使用相同的模数和不同的公钥指数可能导致共模攻击
证明:
1 2 3 4 5 6 7 8 9 10 11 | 明文m、模数n相同,公钥指数e、密文c不同,gcd(e1,e2) = = 1 ,也就是e1和e2互质时 e1 * s1 + e2 * s3 = 1 有唯一的解 由于: c1 = = m^e1 mod n c2 = = m e2 mod n 那么: (c1^s1 * c2 ^ s2) mod n = ( (m^e1 mod n)^s1 * (m^e2 mod n)^s2 )mod n = m^(e1 * s1) * m^(e2 * s2) mod n = m mod n |
当n不变,知道n,e1,e2,c1,c2 可以在不知道d1,d2情况下,解出m。
题目:RSA_what:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | from Crypto.Util.number import bytes_to_long, getPrime from random import randint from gmpy2 import powmod p = getPrime( 2048 ) q = getPrime( 2048 ) N = p * q Phi = (p - 1 ) * (q - 1 ) def get_enc_key(N,Phi): e = getPrime(N) if Phi % e = = 0 : return get_enc_key(N, Phi) else : return e e1 = get_enc_key(randint( 10 , 12 ), Phi) e2 = get_enc_key(randint( 10 , 12 ), Phi) fr = open (r "./base64" , "rb" ) #flag is in this file f1 = open (r "./HUB1" , "wb" ) f2 = open (r "./HUB2" , "wb" ) base64 = fr.read( 255 ) f1.write( "%d\n%d\n" % (N, e1)) f2.write( "%d\n%d\n" % (N, e2)) while len (base64)> 0 : pt = bytes_to_long(base64) ct1 = powmod(pt, e1, N) ct2 = powmod(pt, e2, N) f1.write( "\n%d" % ct1) f2.write( "\n%d" % ct2) base64 = fr.read( 255 ) fr.close() f1.close() f2.close() |
解题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/usr/bin/python2 import gmpy2 from Crypto.Util.number import long_to_bytes f1 = open ( "./HUB1" , "r" ) f2 = open ( "./HUB2" , "r" ) data1 = f1.readlines() data2 = f2.readlines() n = int (data1[ 0 ]) e1 = int (data1[ 1 ]) c1 = int (data1[ 3 ]) e2 = int (data2[ 1 ]) c2 = int (data2[ 3 ]) _, r, s = gmpy2.gcdext(e1, e2) m = pow (c1, r, n) * pow (c2, s, n) % n print long_to_bytes(m) |
这道题解出来后是base64加密后的字符串,实际上没有看上去那么简单,这里涉及到base64隐写,不过不是本文的主题,先暂且不管
6.广播攻击:
原理:
对于相同的明文,使用相同的指数e和不同的模数n1,n2...ni加密得到i组密文(i>=e),可以使用中国剩余定理解出明文
题目:buuctf-rsa4:
1 2 3 4 5 6 7 8 | N = 331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004 c = 310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243 N = 302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114 c = 112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344 N = 332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323 c = 10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242 |
解题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/usr/bin/python2 import gmpy2 import time from Crypto.Util.number import long_to_bytes def CRT(items): N = reduce ( lambda x, y: x * y, (i[ 1 ] for i in items)) result = 0 for a, n in items: m = N / n d, r, s = gmpy2.gcdext(n, m) if d ! = 1 : raise Exception( "Input not pairwise co-prime" ) result + = a * s * m return result % N, N n = [ 129114230505356333697118994510021413915051088225570531043026917550451581564734952308651566723784981323900403426111056537185011193232603296112121643742691356399992969898010827710994350803494919151948423732426591598888439712920344266205641475348312727365971717305409127667391782677854219689063549759596429716629 , 109269702205029292120022054633721536134438763741801805368759852020529400112797868566931991813909053016228871499067304592740926931055426540840268677218282537450757063806695831503892336975370479004151114020279110611956433492281834217463178735931660370487895538198474855043942908224106013915984721193047940206159 , 130184984206907873325788608067133260010668825744109785989754700869397713689450907426005869455386099782561530247238688647088683853688926890638399087109982966623800264662846723141786785531512452737825132399495839974974884122270947543684537604890177662807013640102549749593966105133111628112742472630785570141963 ] c = [ 112820376318708309511883266356668393396816131447182791445506209031700236878469506355658352414748854472099361508824474365112325602319862842561436679067358900089331778617100580343694334226208753320435002324108477884950933641216044198203776075918323272795752182687450526442079367110656868374931125538339145721573 , 45651293556966072304818630107703140982560165499022836594523320391474750266281527820821435052904791681898782443840766880327957385288649094238886877657228597671521358830021677304123300882210216797719566693160533018601632768048713030788957904378243453859832229603157052843135978639276611231634399594108602071349 , 7145575537980676074780210417817024536632595547590648616669010213946256431795860784357127920679439181517662499063976244238924613193503273987203026894830988537974932336129245277788828190575305229420617551083516420170192425247732269483299819348769856966536443995217830327641185916042049253075074223777360483322 ] e = 3 data = zip (c, n) x, n = CRT(data) m = gmpy2.iroot(gmpy2.mpz(x), e)[ 0 ].digits() m = long_to_bytes(m) print m |
7.已知e和d,求p,q
原理:
当已知e,n,可以通过算法快速求得p和q
详细算法见:
https://www.di-mgt.com.au/rsa_factorize_n.html
例题:MRCTF2020Easy_RSA(部分)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def gen_q(): p = getPrime( 1024 ) q = getPrime( 1024 ) assert (p < q) n = p * q print ( "Q_n = " , n) e = getRandomNBitInteger( 53 ) F_n = (p - 1 ) * (q - 1 ) while gcd(e, F_n) ! = 1 : e = getRandomNBitInteger( 53 ) d = invert(e, F_n) print ( "Q_E_D = " , e * d) factor2 = 2021 * p - 2020 * q if factor2 < 0 : factor2 = ( - 1 ) * factor2 return sympy.nextprime(factor2) |
1 2 | Q_n = 20714298338160449749545360743688018842877274054540852096459485283936802341271363766157976112525034004319938054034934880860956966585051684483662535780621673316774842614701726445870630109196016676725183412879870463432277629916669130494040403733295593655306104176367902352484367520262917943100467697540593925707162162616635533550262718808746254599456286578409187895171015796991910123804529825519519278388910483133813330902530160448972926096083990208243274548561238253002789474920730760001104048093295680593033327818821255300893423412192265814418546134015557579236219461780344469127987669565138930308525189944897421753947 Q_E_D = 100772079222298134586116156850742817855408127716962891929259868746672572602333918958075582671752493618259518286336122772703330183037221105058298653490794337885098499073583821832532798309513538383175233429533467348390389323225198805294950484802068148590902907221150968539067980432831310376368202773212266320112670699737501054831646286585142281419237572222713975646843555024731855688573834108711874406149540078253774349708158063055754932812675786123700768288048445326199880983717504538825498103789304873682191053050366806825802602658674268440844577955499368404019114913934477160428428662847012289516655310680119638600315228284298935201 |
解题:
可以看到,这里的p和q都高达1024bit,基本可以排除暴力分解
这时我们知道e*d,和n,可以尝试已知该算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #!/usr/bin/python2 import random def gcd(a, b): if a < b: a, b = b, a while b ! = 0 : temp = a % b a = b b = temp return a def getpq(n,d_e): p = 1 q = 1 while p = = 1 and q = = 1 : k = d_e - 1 g = random.randint ( 0 , n ) while p = = 1 and q = = 1 and k % 2 = = 0 : k / = 2 y = pow (g,k,n) if y! = 1 and gcd(y - 1 ,n)> 1 : p = gcd(y - 1 ,n) q = n / p return p,q def main(): n = 20714298338160449749545360743688018842877274054540852096459485283936802341271363766157976112525034004319938054034934880860956966585051684483662535780621673316774842614701726445870630109196016676725183412879870463432277629916669130494040403733295593655306104176367902352484367520262917943100467697540593925707162162616635533550262718808746254599456286578409187895171015796991910123804529825519519278388910483133813330902530160448972926096083990208243274548561238253002789474920730760001104048093295680593033327818821255300893423412192265814418546134015557579236219461780344469127987669565138930308525189944897421753947 d_e = 100772079222298134586116156850742817855408127716962891929259868746672572602333918958075582671752493618259518286336122772703330183037221105058298653490794337885098499073583821832532798309513538383175233429533467348390389323225198805294950484802068148590902907221150968539067980432831310376368202773212266320112670699737501054831646286585142281419237572222713975646843555024731855688573834108711874406149540078253774349708158063055754932812675786123700768288048445326199880983717504538825498103789304873682191053050366806825802602658674268440844577955499368404019114913934477160428428662847012289516655310680119638600315228284298935201 p,q = getpq(n,d_e) print (p) print (q) if __name__ = = '__main__' : main() |
8.n分解成多个素数
原理:
rsa加密基本原理
需要严格按照欧拉函数的定义来求解phi
例题:15年山东大学生爱好者线上赛
1 2 3 4 | n = 544187306850902797629107353619267427694837163600853983242783 e = 39293 c = 439254895818320413408827022398053685867343267971712332011972 m = ??? |
解题:
n = p * q * r
那么φ(n) = (q-1) * (p-1) * (r-1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import long_to_bytes n = 544187306850902797629107353619267427694837163600853983242783 e = 39293 c = 439254895818320413408827022398053685867343267971712332011972 p = 67724172605733871 q = 11571390939636959887 r = 694415063702720454699679 phi = (p - 1 ) * (q - 1 ) * (r - 1 ) d = gmpy2.invert(e, phi) m = pow (c, d, n) print (long_to_bytes(m)) |
9.dp泄漏攻击
原理:
dp本来是为了加速rsa加解密效率的,不过由于dp和p的关系相当密切,所以当dp泄漏也有相当大的危害
1 2 3 4 | dp = d % (p - 1 ) dq = d % (q - 1 ) dp * e = 1 mod(p - 1 ) dq * e = 1 mod(q - 1 ) |
例题:buuctf-RSA1
1 2 3 4 5 | p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852 |
解题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/usr/bin/python2 import gmpy2 from Crypto.Util.number import long_to_bytes p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852 InvQ = gmpy2.invert(q,p) mp = pow (c,dp,p) mq = pow (c,dq,q) m = (((mp - mq) * InvQ) % p) * q + mq print (long_to_bytes(m)) |
进阶攻击方式
1.私钥文件修复
题目:Jarvis OJ -Crypto-God Like RSA
题目给出了密文文件,公钥和破损的私钥文件(这里就不放上来了)
解题:
首先读出公钥信息和破损的私钥信息填入以下脚本即可恢复出完整的私钥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | #!/usr/bin/python2 import re import pickle from itertools import product from libnum import invmod, gcd def solve_linear(a, b, mod): if a & 1 = = 0 or b & 1 = = 0 : return None return (b * invmod(a, mod)) & (mod - 1 ) # hack for mod = power of 2 def to_n(s): s = re.sub(r "[^0-9a-f]" , "", s) return int (s, 16 ) def msk(s): cleaned = " ".join(map(lambda x: x[-2:], s.split(" :"))) return msk_ranges(cleaned), msk_mask(cleaned), msk_val(cleaned) def msk_ranges(s): return [ range ( 16 ) if c = = " " else [ int (c, 16 )] for c in s] def msk_mask(s): return int (" ".join(" 0 " if c == " " else " f" for c in s), 16 ) def msk_val(s): return int (" ".join(" 0 " if c == " " else c for c in s), 16 ) E = 65537 N = to_n( """00:c0:97:78:53:45:64:84:7d:8c:c4:b4:20:e9:33: 58:67:ec:78:3e:6c:f5:f0:5c:a0:3e:ee:dc:25:63: d0:eb:2a:9e:ba:8f:19:52:a2:67:0b:e7:6e:b2:34: b8:6d:50:76:e0:6a:d1:03:cf:77:33:d8:b1:e9:d7: 3b:e5:eb:1c:65:0c:25:96:fd:96:20:b9:7a:de:1d: bf:fd:f2:b6:bf:81:3e:3e:47:44:43:98:bf:65:2f: 67:7e:27:75:f9:56:47:ba:c4:f0:4e:67:2b:da:e0: 1a:77:14:40:29:c1:a8:67:5a:8f:f5:2e:be:8e:82: 31:3d:43:26:d4:97:86:29:15:14:a9:69:36:2c:76: ed:b5:90:eb:ec:6f:ce:d5:ca:24:1c:aa:f6:63:f8: 06:a2:62:cb:26:74:d3:5b:82:4b:b6:d5:e0:49:32: 7b:62:f8:05:c4:f7:0e:86:59:9b:f3:17:25:02:aa: 3c:97:78:84:7b:16:fd:1a:f5:67:cf:03:17:97:d0: c6:69:85:f0:8d:fa:ce:ee:68:24:63:06:24:e1:e4: 4c:f8:e9:ad:25:c7:e0:c0:15:bb:b4:67:48:90:03: 9b:20:7f:0c:17:eb:9d:13:44:ab:ab:08:a5:c3:dc: c1:98:88:c5:ce:4f:5a:87:9b:0b:bf:bd:d7:0e:a9: 09:59:81:fa:88:4f:59:60:6b:84:84:ad:d9:c7:25: 8c:e8:c0:e8:f7:26:9e:37:95:7c:e1:48:29:0f:51: e7:bd:98:2f:f6:cc:80:e7:f0:32:0b:89:51:92:4e: c2:6d:50:53:2b:3b:77:72:d1:bd:1a:1f:92:d7:12: 79:61:61:c5:a4:7e:b3:85:eb:f0:7c:6d:46:03:c5: e6:d5:81:2c:ba:7e:ea:8d:51:7d:63:55:34:2a:b6: d4:dc:31:5a:f1:99:e3:dc:8c:83:0b:a2:2a:d5:3c: 41:48:41:54:1a:a9:e8:b6:70:bf:d3:fe:ed:19:17: 14:94:13:b3:17:e3:8b:8e:6f:53:ed:e2:44:e8:4a: 32:d6:5c:0d:a8:80:f5:fc:02:e9:46:55:d5:a4:d3: e7:c6:30:77:f9:73:e9:44:52:d8:13:9d:5d:bf:9e: fa:3a:b5:96:79:82:5b:cd:19:5c:06:a9:00:96:fd: 4c:a4:73:88:1a:ec:3c:11:de:b9:3d:e0:50:00:1e: ac:21:97:a1:96:7d:6b:15:f9:6c:c9:34:7f:70:d7: 9d:2d:d1:48:4a:81:71:f8:12:dd:32:ba:64:31:60: 08:26:4b:09:22:03:83:90:17:7f:f3:a7:72:57:bf: 89:6d:e4:d7:40:24:8b:7b:bd:df:33:c0:ff:30:2e: e8:6c:1d""" ) p_ranges, pmask_msk, pmask_val = msk( """ 0: e: : : :c :c : : : :b : : : : : :ab: e: 2: 8:c : : : 1:6 :6 : 6: f:d9: 0: 8 :5c:7 :06: : : :0 : 3:5 :4b: :6 : : : 2 : :6 : : : :2 :bc: c: :85:1 : 1:d : 3: 1:b4: : b: 1: 3: d:a : : :6e: 0:b :2 : : :b : :9 :e : :82:8d: : :13: : : a: a: : :4 : :c : f: : :7 :e :0a: : : b: 5: : e:91:3 : :3c: 9: : 6: : :b5:7d: 1: : : : :b :a1:99:6 :4 :3 :c :1a:02:4 : : 9: 9 :f : d:bd: :0 : : : :b3: : 4: :e9: 9: : d: : :7 : :93: : e:dc: : 0: :e7: : e : :2 : b: 2:5 : : : : : c:5f: : :e2: : : 9: :2a: : e: : :2 : :9f: 7:3 : : b : f:b : : 8: 7: : :f :6 :e :c : :3 : : f7: 5: 8: 5: : : : : : 8: e: :03: c: : 33:76:e : 1:7 : c: : 0: :0b: : a: : 2: 9: :c8:bf: : :06: 7:d5: :02: c:b :e2: 7:2 : : """ ) q_ranges, qmask_msk, qmask_val = msk( """ 0: f: :d0: 1:55: 4:31: : b:c4:8 : : e: d: 34: 3:f : : : : : 8:99:1 : : a:0 : :4 : 0 : :f : :a4:41:2 : :a : : 1: : a: c: : : : 9: : : 2:f4: f: : : : :1 : 4:9 : a : : :79:0 : : : : : 2: 8:b : :4 : 8: :9b: 1: :d : :f :e4: :4 :c :e : :3 : : 7:2 : :d :8 :2 :7 : :d :67:fc:e : 0:f9: 7: 8 : : : :1 :2f: :51: : :2e:0a: e:3d: 6: b : :dd: : 0:fb: :f4: : : :b4: 9:c : : a: : : :d : : :6b: 2: :9b: a:60: :d6: 0:4f:16:d1: : :5 :fc: :f : :8 : : : : 1: 6:e1:9 : e:4 : 6: c: d:d :73: 3: : :7 : :8 : 9: :3b:f : 2: : :f1: e: : :1e: : 8 : : : 6:0 : 4:99:e : : 5: : : 4: : : : a:81:64: :7 :f : 9: d: :9 : : 7:93:f : ac:8c: : 8: : 0: d: 8: :7 : :1d: :f : : 1 :a :6 :8 : :60: :b3: : : :89: : :14: :5 """ ) _, dmask_msk, dmask_val = msk( """ : : : f:8 :a5:d : 2: 0:b :7 : : 1: : 4: 1:0d: :3 : :6 : : : b: : : :e : : : 0e: 0:db: :1a:1c:c0: : e: : :99:bc:8 :a5: 7 :7 :7 : b: : : 8: 8: :7 :55: 2: : :f : b2: : :b :f :4 : : 8: :b : : : : 0: : 0 : :6 :9 : : : : b: 4: : 0: a: 5:07:b : 9: c:9a: 9: : 7:9e: : b:60:f : : : :0 : : 3:0 : : : : 1:b : : : b: 6:0 :f : : : 2:18: 6: b:1 : : : : :d3:f3: :a : : 3: : : : : 3: d: 1: 2:7 : : d: : 2: d: : : d:4 : :d : :6d: c:a :b6: : : : 1: 69: : 7: :89: :c :8 :61: d:25: 3:7 :1b: 4: b : :8 :55: :49: 1:2 :3 : :1 :e9:a8: 3: : 9 : : 1:f8:d3: :e : :d : :9 :b6: : :71: 1 : :c1: : b: 1: : 6:e : :64: : :1a:c : : b: :bf:c : : 0: : 8:a :4 : :26:a :5 : 6 : : : :eb: :e5: a: :3e:f9:10:0 : : : 6:0 : : 8: : 1:72: c:0 : f:5 : f:9c: 0: e: 7:b : : : : :d9: 4: : e:c :68: : : : c: :3a: : :a0:ea: 3: 4: :72:a :d : 8: : :0d:5 :0 : a: 7:c :bb: 6: 4:a :ce:d :2 : 1: : :17:6 : : c: b: : f: :3 : 5:6 :3 :0e: : 7:c :3e: 2: 9: 7: 6: f: e: f: 9: :f3: 9: a :c1:6 : : 1:9 : :43: : f: 5: :0 :27: 4: 4 :a : :e9: : 8: 4:3 :8a: 6:16:d5:c : e: e: :d : c:b :a8: : 7: : 9: :7 :7d: : : : : : :4 :2 : : 3: 3: 6: : : :7b:0 : : e: :0 : :a : : 5: : : : 5:1 :82:c :0d: 4 :2 :fd:36: 5:50:0 : : :d : f: 6: : :e : 0 : : :ce: :9e:8 : :0 :d :07:b3: : : : 0 :e4: : :68:b :c : : c:5 : : :3 : 7: 2: c:e0: :5 : : :b4: :ef: 7: :1 :e : 0:f : :6 : : : :e0:c :3 : : : 3: : d: : : 3: 3: c: a: :b : a:71: 3: 0:a : :4 :5d: : 0 :4 """ ) _, dpmask_msk, dpmask_val = msk( """ : 3:2a: : d: : : : :0 :1 : f: : : 6: 1 :2 :1b:07: a:e :b :c5:58:7 : :e8: 7: 1: c: : 1:b :a0: 4:0f:5 :67: :3 :7 :6 :f9: : c: :79: 0:1 :65: :8 : :99: d:d : :2 :9 :0 : e: :0 : : : : d: :d :7 :6 :a9: a:8b: b: : : 7: a:37: : :7 :1 :6 : :c2: 7:6 :b : e: : : : : : :b :3a:5 : : : : : : : : :cd:8 : : d: :7 : 3: : f:e : c: : : a: :c : f:c : 7:b :5 : : :2 :8 :8 :6 : 0a: a: : :3 :db: : 4:00: : d: :b : 5: : 20: 2: 5: :82: : 0: 6: :8a: :7 : : 8: : 4: 1: : : : 8:46: : : : : : 0:f :c8: 2 : : c:7 : : 1: : :2 : 0: 5: : : 1:9b: 6:9 : 0:74: :c : :e : : :cb:b :3 :3 : : 2: : :47: :2 : 0:5 : : : d: 6:83: : : :c7: : :0b: : : c: :3 :8 : :9 :4 : 7: 5 :c0:fe: :f9: 1: :0 : e: 8:02: : f: :c : 55:61""" ) _, dqmask_msk, dqmask_val = msk( """ :0b:7 :4 :0 : 0:6 : 7:7e: : 5: : 7: : a: a :d : 0: 6: 4:86: : :8 : : : : :e :8f: 9: : : : 1: :2 : : 7: b:1 :5 : f: :8 : :d :21: :e : d: :c9:e : b: : :1 : : : :d :a2:b7: : : :f3: :42: :e : c: :f : : 0:f :7 : 4: 5:34: :4 : c: : :8 :d : 8: 5 :af: 3:1d: 5:4 : :2 : :6 :c : 6:a :1 :5 : a:9 : :d : : :0a:a1: :f :7 :9 :b : : : f:2 :27: f: :0 :f6:4d: : : : : :5 : : 4:08: : 5: : 8: 5: : : :18: 4: 8:57: 2: f: a: : :a8: f: c:f : e: 1:9 :c : 4:9 : : : : : : : 1: :2 : :d1: : 6:e : d: : : f:04:2 :8d: : 3: : :b : 8: :d6: : 2: : : :6 : : f: : : 0:6 : :51: :48:19: : : :69:4 : c: :c : : f: :f4:d : : f: d:0 :0d:b :3 : 3:2 : : :6 : b:5 :2 : : c: 1:5a: f:f : : :7e:3e: :d :f :0 : d: c: 6: 1""" ) def search(K, Kp, Kq, check_level, break_step): max_step = 0 cands = [ 0 ] for step in range ( 1 , break_step + 1 ): #print " ", step, "( max =", max_step, ")" max_step = max (step, max_step) mod = 1 << ( 4 * step) mask = mod - 1 cands_next = [] for p, new_digit in product(cands, p_ranges[ - step]): pval = (new_digit << ((step - 1 ) * 4 )) | p if check_level > = 1 : qval = solve_linear(pval, N & mask, mod) if qval is None or not check_val(qval, mask, qmask_msk, qmask_val): continue if check_level > = 2 : val = solve_linear(E, 1 + K * (N - pval - qval + 1 ), mod) if val is None or not check_val(val, mask, dmask_msk, dmask_val): continue if check_level > = 3 : val = solve_linear(E, 1 + Kp * (pval - 1 ), mod) if val is None or not check_val(val, mask, dpmask_msk, dpmask_val): continue if check_level > = 4 : val = solve_linear(E, 1 + Kq * (qval - 1 ), mod) if val is None or not check_val(val, mask, dqmask_msk, dqmask_val): continue if pval * qval = = N: print "Kq =" , Kq print "pwned" print "p =" , pval print "q =" , qval p = pval q = qval d = invmod(E, (p - 1 ) * (q - 1 )) coef = invmod(p, q) from Crypto.PublicKey import RSA print RSA.construct( map ( long , (N, E, d, p, q, coef))).exportKey() quit() cands_next.append(pval) if not cands_next: return False cands = cands_next return True def check_val(val, mask, mask_msk, mask_val): test_mask = mask_msk & mask test_val = mask_val & mask return val & test_mask = = test_val # K = 4695 # Kp = 15700 # Kq = 5155 for K in range ( 1 , E): if K % 100 = = 0 : print "checking" , K if search(K, 0 , 0 , check_level = 2 , break_step = 20 ): print "K =" , K break for Kp in range ( 1 , E): if Kp % 1000 = = 0 : print "checking" , Kp if search(K, Kp, 0 , check_level = 3 , break_step = 30 ): print "Kp =" , Kp break for Kq in range ( 1 , E): if Kq % 100 = = 0 : print "checking" , Kq if search(K, Kp, Kq, check_level = 4 , break_step = 9999 ): print "Kq =" , Kq break |
解出私钥后,写入到文件中,用openssl解密即可(不过需要注意的是这依然是用oaep的填充方式,需要指明)
2.对e爆破
题目1:[HDCTF2019]bbbbbbrsa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | from base64 import b64encode as b32encode from gmpy2 import invert,gcd,iroot from Crypto.Util.number import * from binascii import a2b_hex,b2a_hex import random flag = "******************************" nbit = 128 p = getPrime(nbit) q = getPrime(nbit) n = p * q print p print n phi = (p - 1 ) * (q - 1 ) e = random.randint( 50000 , 70000 ) while True : if gcd(e,phi) = = 1 : break ; else : e - = 1 ; c = pow ( int (b2a_hex(flag), 16 ),e,n) print b32encode( str (c))[:: - 1 ] |
这道题e的大致范围已经给出,可以尝试爆破
不过加密脚本的第一行有点坑
1 | from base64 import b64encode as b32encode |
(应该是出题人故意)把人误导成base32解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import long_to_bytes import base64 p = 177077389675257695042507998165006460849 n = 37421829509887796274897162249367329400988647145613325367337968063341372726061 q = n / / p phi = (p - 1 ) * (q - 1 ) c = '==gMzYDNzIjMxUTNyIzNzIjMyYTM4MDM0gTMwEjNzgTM2UTN4cjNwIjN2QzM5ADMwIDNyMTO4UzM2cTM5kDN2MTOyUTO5YDM0czM3MjM' c = int ( str ((base64.b64decode(c[:: - 1 ])))[ 2 : - 1 ]) for e in range ( 50000 , 70000 ): if gmpy2.gcd(e,phi) = = 1 : d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) try : print (long_to_bytes(m).decode()) except : continue |
题目2:[BJDCTF2020]RSA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from Crypto.Util.number import getPrime,bytes_to_long flag = open ( "flag" , "rb" ).read() p = getPrime( 1024 ) q = getPrime( 1024 ) assert (e< 100000 ) n = p * q m = bytes_to_long(flag) c = pow (m,e,n) print c,n print pow ( 294 ,e,n) p = getPrime( 1024 ) n = p * q m = bytes_to_long( "BJD" * 32 ) c = pow (m,e,n) print c,n |
也是对e爆破,不过我们可以通过这道题来对比pow()函数和gmpy2.powmod()的速度
pow:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/usr/bin/python import libnum import gmpy2 from Crypto.Util.number import long_to_bytes n = 13508774104460209743306714034546704137247627344981133461801953479736017021401725818808462898375994767375627749494839671944543822403059978073813122441407612530658168942987820256786583006947001711749230193542370570950705530167921702835627122401475251039000775017381633900222474727396823708695063136246115652622259769634591309421761269548260984426148824641285010730983215377509255011298737827621611158032976420011662547854515610597955628898073569684158225678333474543920326532893446849808112837476684390030976472053905069855522297850688026960701186543428139843783907624317274796926248829543413464754127208843070331063037 c1 = 381631268825806469518166370387352035475775677163615730759454343913563615970881967332407709901235637718936184198930226303761876517101208677107311006065728014220477966000620964056616058676999878976943319063836649085085377577273214792371548775204594097887078898598463892440141577974544939268247818937936607013100808169758675042264568547764031628431414727922168580998494695800403043312406643527637667466318473669542326169218665366423043579003388486634167642663495896607282155808331902351188500197960905672207046579647052764579411814305689137519860880916467272056778641442758940135016400808740387144508156358067955215018 for e in range ( 10000000000 ): if e % 1000 = = 0 : print (e) if c1 = = pow ( 294 ,e,n): print ( "found" ) print (e) break n2 = 12806210903061368369054309575159360374022344774547459345216907128193957592938071815865954073287532545947370671838372144806539753829484356064919357285623305209600680570975224639214396805124350862772159272362778768036844634760917612708721787320159318432456050806227784435091161119982613987303255995543165395426658059462110056431392517548717447898084915167661172362984251201688639469652283452307712821398857016487590794996544468826705600332208535201443322267298747117528882985955375246424812616478327182399461709978893464093245135530135430007842223389360212803439850867615121148050034887767584693608776323252233254261047 p = gmpy2.gcd(n,n2) q = n / / p #e = 52361 phi = (q - 1 ) * (p - 1 ) c = 12641635617803746150332232646354596292707861480200207537199141183624438303757120570096741248020236666965755798009656547738616399025300123043766255518596149348930444599820675230046423373053051631932557230849083426859490183732303751744004874183062594856870318614289991675980063548316499486908923209627563871554875612702079100567018698992935818206109087568166097392314105717555482926141030505639571708876213167112187962584484065321545727594135175369233925922507794999607323536976824183162923385005669930403448853465141405846835919842908469787547341752365471892495204307644586161393228776042015534147913888338316244169120 d = libnum.invmod(e,phi) m = pow (c,d,n) print (long_to_bytes(m)) |
用时信息:
3.03s user 0.01s system 99% cpu 3.050 total
gmpy2.powmod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import long_to_bytes n = 13508774104460209743306714034546704137247627344981133461801953479736017021401725818808462898375994767375627749494839671944543822403059978073813122441407612530658168942987820256786583006947001711749230193542370570950705530167921702835627122401475251039000775017381633900222474727396823708695063136246115652622259769634591309421761269548260984426148824641285010730983215377509255011298737827621611158032976420011662547854515610597955628898073569684158225678333474543920326532893446849808112837476684390030976472053905069855522297850688026960701186543428139843783907624317274796926248829543413464754127208843070331063037 c1 = 381631268825806469518166370387352035475775677163615730759454343913563615970881967332407709901235637718936184198930226303761876517101208677107311006065728014220477966000620964056616058676999878976943319063836649085085377577273214792371548775204594097887078898598463892440141577974544939268247818937936607013100808169758675042264568547764031628431414727922168580998494695800403043312406643527637667466318473669542326169218665366423043579003388486634167642663495896607282155808331902351188500197960905672207046579647052764579411814305689137519860880916467272056778641442758940135016400808740387144508156358067955215018 for e in range ( 10000000000 ): if e % 1000 = = 0 : print (e) if c1 = = gmpy2.powmod( 294 ,e,n): print ( "found" ) print (e) break n2 = 12806210903061368369054309575159360374022344774547459345216907128193957592938071815865954073287532545947370671838372144806539753829484356064919357285623305209600680570975224639214396805124350862772159272362778768036844634760917612708721787320159318432456050806227784435091161119982613987303255995543165395426658059462110056431392517548717447898084915167661172362984251201688639469652283452307712821398857016487590794996544468826705600332208535201443322267298747117528882985955375246424812616478327182399461709978893464093245135530135430007842223389360212803439850867615121148050034887767584693608776323252233254261047 p = gmpy2.gcd(n,n2) q = n / / p #e = 52361 phi = (q - 1 ) * (p - 1 ) c = 12641635617803746150332232646354596292707861480200207537199141183624438303757120570096741248020236666965755798009656547738616399025300123043766255518596149348930444599820675230046423373053051631932557230849083426859490183732303751744004874183062594856870318614289991675980063548316499486908923209627563871554875612702079100567018698992935818206109087568166097392314105717555482926141030505639571708876213167112187962584484065321545727594135175369233925922507794999607323536976824183162923385005669930403448853465141405846835919842908469787547341752365471892495204307644586161393228776042015534147913888338316244169120 d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) print (long_to_bytes(m)) |
用时信息:
1.30s user 0.00s system 99% cpu 1.310 total
可以看到,gmpy2中的powmod()函数用时不到pow()函数的二分之一,所以以后优先使用gmpy2.powmod()函数
题目3:[RoarCTF2019]babyRSA
1 2 3 4 5 6 | A = (((y % x) * * 5 ) % (x % y)) * * 2019 + y * * 316 + (y + 1 ) / x p = next_prime(z * x * y) q = next_prime(z) A = 2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724 n = 117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127 c = 41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128 |
解题:
题目给出了A和p,q的关系,一通花里胡哨的运算之后得到A
以我已知的知识想不到什么好的算法
不过可以直接分解n得到p和q
当我们做完这些后,发现题目并没有告知e,盲猜e = 65537,结果正好是
当然平时做题我们还是严谨一点,尝试爆破e
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import * q = 842868045681390934539739959201847552284980179958879667933078453950968566151662147267006293571765463137270594151138695778986165111380428806545593588078365331313084230014618714412959584843421586674162688321942889369912392031882620994944241987153078156389470370195514285850736541078623854327959382156753458569 p = 139916095583110895133596833227506693679306709873174024876891023355860781981175916446323044732913066880786918629089023499311703408489151181886568535621008644997971982182426706592551291084007983387911006261442519635405457077292515085160744169867410973960652081452455371451222265819051559818441257438021073941183 c = 41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128 n = q * p phi = (q - 1 ) * (p - 1 ) for e in range ( 1 , 100000 ): if e % 1000 = = 0 : print (e) if isPrime(e): try : d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) m = str (long_to_bytes(m)) if "{" in m and "}" in m and "CTF" in m: print (m) break except : continue |
关于e = 65537的说明
NIST SP800-78 Rev 1 (2007) 曾强调“不允许使用比65537更低的公钥指数e”,但PKCS#1却从未有过类似的建议。e=65537=(2^16+1),其签名/加密运算只需要17次模乘,性能也算不错。65537可以在安全上和性能上做出一个很好的平衡,因此大多数加密的e都默认为65537
对于e未知的题型的总结:
可以优先尝试e == 65537,不行再爆破
3.已知p和q的最小公倍数
题目:[NPUCTF2020]EzRSA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from gmpy2 import lcm , powmod , invert , gcd , mpz from Crypto.Util.number import getPrime from sympy import nextprime from random import randint p = getPrime( 1024 ) q = getPrime( 1024 ) n = p * q gift = lcm(p - 1 , q - 1 ) e = 54722 flag = b 'NPUCTF{******************}' m = int .from_bytes(flag , 'big' ) c = powmod(m , e , n) print ( 'n: ' , n) print ( 'gift: ' , gift) print ( 'c: ' , c) #n: 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121 #gift: 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104 #c: 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319 |
解题:
已知n = q
gift = lcm(q-1,p-1)
= (q-1)*(p-1) // gcd(q-1,p-1)
又因为(q-1)*(p-1) 约等于 q*p = n
gift 约等于 n // gcd(q-1,p-1)
于是可以得出gcd(q-1,p-1) 约等于 n // gift
于是得出gcd(q-1,p-1)约等于8
设k = gcd(q-1,p-1) ( k 约等于8,于是爆破k的取值范围为0<k<10)
最后得到q,p,e,又由于gcd(e,phi) != 1
于是:
new_e = e//2
d = gmpy2.invert(e,phi)
m = gmpy2.powmod(c,d,n)
m = gmpy2.iroot(m,2)[0]
m = long_to_bytes(m)
可以求出明文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/usr/bin/python import gmpy2 from gmpy2 import lcm , powmod , invert , gcd , mpz from Crypto.Util.number import * n = 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121 # q * p gift = 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104 # lcm((q-1),(p-1)) == (q-1) * (p-1) c = 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319 for k in range ( 1 , 10 ): tmp = gift * k - 1 # q*p - (p+q) q__p = n - tmp #q+p q_p = pow (q__p, 2 ) - 4 * n #(q-p) ^ 2 if q_p < 0 : q_p = - q_p if gmpy2.iroot(q_p, 2 )[ 1 ]: q_p = gmpy2.iroot(q_p, 2 )[ 0 ] q = (q_p + q__p) / / 2 p = q__p - q e = 54722 e = e / / 2 phi = (p - 1 ) * (q - 1 ) d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) m = gmpy2.iroot(m, 2 )[ 0 ] print (long_to_bytes(m)) |
最后两道综合题:
1.[De1CTF2019]babyrsa
题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import binascii from data import e1,e2,p,q1p,q1q,hint,flag n = [ 20129615352491765499340112943188317180548761597861300847305827141510465619670536844634558246439230371658836928103063432870245707180355907194284861510906071265352409579441048101084995923962148527097370705452070577098780246282820065573711015664291991372085157016901209114191068574208680397710042842835940428451949500607613634682684113208766694028789275748528254287705759528498986306494267817198340658241873024800336013946294891687591013414935237821291805123285905335762719823771647853378892868896078424572232934360940672962436849523915563328779942134504499568866135266628078485232098208237036724121481835035731201383423L , 31221650155627849964466413749414700613823841060149524451234901677160009099014018926581094879840097248543411980533066831976617023676225625067854003317018794041723612556008471579060428898117790587991055681380408263382761841625714415879087478072771968160384909919958010983669368360788505288855946124159513118847747998656422521414980295212646675850690937883764000571667574381419144372824211798018586804674824564606122592483286575800685232128273820087791811663878057827386379787882962763290066072231248814920468264741654086011072638211075445447843691049847262485759393290853117072868406861840793895816215956869523289231421L , 29944537515397953361520922774124192605524711306753835303703478890414163510777460559798334313021216389356251874917792007638299225821018849648520673813786772452822809546571129816310207232883239771324122884804993418958309460009406342872173189008449237959577469114158991202433476710581356243815713762802478454390273808377430685157110095496727966308001254107517967559384019734279861840997239176254236069001453544559786063915970071130087811123912044312219535513880663913831358790376650439083660611831156205113873793106880255882114422025746986403355066996567909581710647746463994280444700922867397754748628425967488232530303L , 25703437855600135215185778453583925446912731661604054184163883272265503323016295700357253105301146726667897497435532579974951478354570415554221401778536104737296154316056314039449116386494323668483749833147800557403368489542273169489080222009368903993658498263905567516798684211462607069796613434661148186901892016282065916190920443378756167250809872483501712225782004396969996983057423942607174314132598421269169722518224478248836881076484639837343079324636997145199835034833367743079935361276149990997875905313642775214486046381368619638551892292787783137622261433528915269333426768947358552919740901860982679180791L ] c = [ 19131432661217908470262338421299691998526157790583544156741981238822158563988520225986915234570037383888112724408392918113942721994125505014727545946133307329781747600302829588248042922635714391033431930411180545085316438084317927348705241927570432757892985091396044950085462429575440060652967253845041398399648442340042970814415571904057667028157512971079384601724816308078631844480110201787343583073815186771790477712040051157180318804422120472007636722063989315320863580631330647116993819777750684150950416298085261478841177681677867236865666207391847046483954029213495373613490690687473081930148461830425717614569L , 15341898433226638235160072029875733826956799982958107910250055958334922460202554924743144122170018355117452459472017133614642242411479849369061482860570279863692425621526056862808425135267608544855833358314071200687340442512856575278712986641573012456729402660597339609443771145347181268285050728925993518704899005416187250003304581230701444705157412790787027926810710998646191467130550713600765898234392350153965811595060656753711278308005193370936296124790772689433773414703645703910742193898471800081321469055211709339846392500706523670145259024267858368216902176489814789679472227343363035428541915118378163012031L , 18715065071648040017967211297231106538139985087685358555650567057715550586464814763683688299037897182845007578571401359061213777645114414642903077003568155508465819628553747173244235936586812445440095450755154357646737087071605811984163416590278352605433362327949048243722556262979909488202442530307505819371594747936223835233586945423522256938701002370646382097846105014981763307729234675737702252155130837154876831885888669150418885088089324534892506199724486783446267336789872782137895552509353583305880144947714110009893134162185382309992604435664777436197587312317224862723813510974493087450281755452428746194446L , 2282284561224858293138480447463319262474918847630148770112472703128549032592187797289965592615199709857879008271766433462032328498580340968871260189669707518557157836592424973257334362931639831072584824103123486522582531666152363874396482744561758133655406410364442174983227005501860927820871260711861008830120617056883514525798709601744088135999465598338635794275123149165498933580159945032363880613524921913023341209439657145962332213468573402863796920571812418200814817086234262280338221161622789516829363805084715652121739036183264026120868756523770196284142271849879003202190966150390061195469351716819539183797L ] f = lambda m,e,n,c: pow (m,e,n) = = c assert ( sum ( map (f,[p] * 4 ,[ 4 ] * 4 ,n,c)) = = 4 ) ee1 = 42 ee2 = 3 ce1 = 45722651786340123946960815003059322528810481841378247280642868553607692149509126962872583037142461398806689489141741494974836882341505234255325683219092163052843461632338442529011502378931140356111756932712822516814023166068902569458299933391973504078898958921809723346229893913662577294963528318424676803942288386430172430880307619748186863890050113934573820505570928109017842647598266634344447182347849367714564686341871007505886728393751147033556889217604647355628557502208364412269944908011305064122941446516990168924709684092200183860653173856272384 ce2 = 13908468332333567158469136439932325992349696889129103935400760239319454409539725389747059213835238373047899198211128689374049729578146875309231962936554403287882999967840346216695208424582739777034261079550395918048421086843927009452479936045850799096750074359160775182238980989229190157551197830879877097703347301072427149474991803868325769967332356950863518504965486565464059770451458557744949735282131727956056279292800694203866167270268988437389945703117070604488999247750139568614939965885211276821987586882908159585863514561191905040244967655444219603287214405014887994238259270716355378069726760953320025828158 tmp = 864078778078609835167779565982540757684070450697854309005171742813414963447462554999012718960925081621571487444725528982424037419052194840720949809891134854871222612682162490991065015935449289960707882463387 n = 15911581555796798614711625288508309704791837516232122410440958830726078821069050404012820896260071751380436992710638364294658173571101596931605797509712839622479368850251206419748090059752427303611760004621378226431226983665746837779056271530181865648115862947527212787824629516204832313026456390047768174765687040950636530480549014401279054346098030395100387004111574278813749630986724706263655166289586230453975953773791945408589484679371854113457758157492241225180907090235116325034822993748409011554673180494306003272836905082473475046277554085737627846557240367696214081276345071055578169299060706794192776825039 assert ( pow (e1,ee1,n) = = ce1) assert ( pow (e2 + tmp,ee2,n) = = ce2) e = 46531 n = 16278524034278364842964386062476113517067911891699789991355982121084973951738324063305190630865511554888330215827724887964565979607808294168282995825864982603759381323048907814961279012375346497781046417204954101076457350988751188332353062731641153547102721113593787978587135707313755661153376485647168543680503160420091693269984008764444291289486805840439906620313162344057956594836197521501755378387944609246120662335790110901623740990451586621846212047950084207251595169141015645449217847180683357626383565631317253913942886396494396189837432429078251573229378917400841832190737518763297323901586866664595327850603 c = 14992132140996160330967307558503117255626925777426611978518339050671013041490724616892634911030918360867974894371539160853827180596100892180735770688723270765387697604426715670445270819626709364566478781273676115921657967761494619448095207169386364541164659123273236874649888236433399127407801843412677293516986398190165291102109310458304626261648346825196743539220198199366711858135271877662410355585767124059539217274691606825103355310348607611233052725805236763220343249873849646219850954945346791015858261715967952461021650307307454434510851869862964236227932964442289459508441345652423088404453536608812799355469 hint = int (binascii.hexlify(hint), 16 ) assert (q1p * q1q = = n) assert (q1p<q1q) assert (c = = pow (hint,e,n)) flag = int (binascii.hexlify(flag), 16 ) q1 = q1p q2 = 114401188227479584680884046151299704656920536168767132916589182357583461053336386996123783294932566567773695426689447410311969456458574731187512974868297092638677515283584994416382872450167046416573472658841627690987228528798356894803559278308702635288537653192098514966089168123710854679638671424978221959513 c1 = 262739975753930281690942784321252339035906196846340713237510382364557685379543498765074448825799342194332681181129770046075018122033421983227887719610112028230603166527303021036386350781414447347150383783816869784006598225583375458609586450854602862569022571672049158809874763812834044257419199631217527367046624888837755311215081173386523806086783266198390289097231168172692326653657393522561741947951887577156666663584249108899327053951891486355179939770150550995812478327735917006194574412518819299303783243886962455399783601229227718787081785391010424030509937403600351414176138124705168002288620664809270046124 c2 = 7395591129228876649030819616685821899204832684995757724924450812977470787822266387122334722132760470911599176362617225218345404468270014548817267727669872896838106451520392806497466576907063295603746660003188440170919490157250829308173310715318925771643105064882620746171266499859049038016902162599261409050907140823352990750298239508355767238575709803167676810456559665476121149766947851911064706646506705397091626648713684511780456955453552020460909638016134124590438425738826828694773960514221910109473941451471431637903182205738738109429736425025621308300895473186381826756650667842656050416299166317372707709596 assert (c1 = = pow (flag,e1,p * q1)) assert (c2 = = pow (flag,e2,p * q2)) |
解题:
本题过程大致可以分为三部分:
解得e1和e3
解得hint和q1
解得flag
1.解得e1和e3
通过这两句断言:
1 2 3 4 5 6 7 8 | ee1 = 42 ee2 = 3 ce1 = 45722651786340123946960815003059322528810481841378247280642868553607692149509126962872583037142461398806689489141741494974836882341505234255325683219092163052843461632338442529011502378931140356111756932712822516814023166068902569458299933391973504078898958921809723346229893913662577294963528318424676803942288386430172430880307619748186863890050113934573820505570928109017842647598266634344447182347849367714564686341871007505886728393751147033556889217604647355628557502208364412269944908011305064122941446516990168924709684092200183860653173856272384 ce2 = 13908468332333567158469136439932325992349696889129103935400760239319454409539725389747059213835238373047899198211128689374049729578146875309231962936554403287882999967840346216695208424582739777034261079550395918048421086843927009452479936045850799096750074359160775182238980989229190157551197830879877097703347301072427149474991803868325769967332356950863518504965486565464059770451458557744949735282131727956056279292800694203866167270268988437389945703117070604488999247750139568614939965885211276821987586882908159585863514561191905040244967655444219603287214405014887994238259270716355378069726760953320025828158 tmp = 864078778078609835167779565982540757684070450697854309005171742813414963447462554999012718960925081621571487444725528982424037419052194840720949809891134854871222612682162490991065015935449289960707882463387 n = 15911581555796798614711625288508309704791837516232122410440958830726078821069050404012820896260071751380436992710638364294658173571101596931605797509712839622479368850251206419748090059752427303611760004621378226431226983665746837779056271530181865648115862947527212787824629516204832313026456390047768174765687040950636530480549014401279054346098030395100387004111574278813749630986724706263655166289586230453975953773791945408589484679371854113457758157492241225180907090235116325034822993748409011554673180494306003272836905082473475046277554085737627846557240367696214081276345071055578169299060706794192776825039 assert ( pow (e1,ee1,n) = = ce1) assert ( pow (e2 + tmp,ee2,n) = = ce2) |
可以建立两个方程,由于两个e都很小,考虑低加密指数攻击:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #!/usr/bin/python import gmpy2 ee1 = 42 ee2 = 3 ce1 = 45722651786340123946960815003059322528810481841378247280642868553607692149509126962872583037142461398806689489141741494974836882341505234255325683219092163052843461632338442529011502378931140356111756932712822516814023166068902569458299933391973504078898958921809723346229893913662577294963528318424676803942288386430172430880307619748186863890050113934573820505570928109017842647598266634344447182347849367714564686341871007505886728393751147033556889217604647355628557502208364412269944908011305064122941446516990168924709684092200183860653173856272384 ce2 = 13908468332333567158469136439932325992349696889129103935400760239319454409539725389747059213835238373047899198211128689374049729578146875309231962936554403287882999967840346216695208424582739777034261079550395918048421086843927009452479936045850799096750074359160775182238980989229190157551197830879877097703347301072427149474991803868325769967332356950863518504965486565464059770451458557744949735282131727956056279292800694203866167270268988437389945703117070604488999247750139568614939965885211276821987586882908159585863514561191905040244967655444219603287214405014887994238259270716355378069726760953320025828158 n = 15911581555796798614711625288508309704791837516232122410440958830726078821069050404012820896260071751380436992710638364294658173571101596931605797509712839622479368850251206419748090059752427303611760004621378226431226983665746837779056271530181865648115862947527212787824629516204832313026456390047768174765687040950636530480549014401279054346098030395100387004111574278813749630986724706263655166289586230453975953773791945408589484679371854113457758157492241225180907090235116325034822993748409011554673180494306003272836905082473475046277554085737627846557240367696214081276345071055578169299060706794192776825039 tmp = 864078778078609835167779565982540757684070450697854309005171742813414963447462554999012718960925081621571487444725528982424037419052194840720949809891134854871222612682162490991065015935449289960707882463387 #--------find e1-------- for k in range ( 200000000 ): c = k * n + ce1 if gmpy2.iroot(c,ee1)[ 1 ]: e1 = gmpy2.iroot(c,ee1)[ 0 ] break #--------check e1------ if ce1 = = gmpy2.powmod(e1,ee1,n): print ( "e1 = %d" % e1) #--------find e2-------- for k in range ( 1000000 ): c = k * n + ce2 if gmpy2.iroot(c, 3 )[ 1 ]: m = gmpy2.iroot(c, 3 )[ 0 ] e2 = m - tmp break #--------check e2------ if ce2 = = gmpy2.powmod((e2 + tmp), 3 ,n): print ( "e2 = %d" % e2) |
解的e1,e2
1 2 | e1 = 15218928658178 e2 = 381791429275130 |
2.解的hint和q1
1 2 3 4 5 6 7 | e = 46531 n = 16278524034278364842964386062476113517067911891699789991355982121084973951738324063305190630865511554888330215827724887964565979607808294168282995825864982603759381323048907814961279012375346497781046417204954101076457350988751188332353062731641153547102721113593787978587135707313755661153376485647168543680503160420091693269984008764444291289486805840439906620313162344057956594836197521501755378387944609246120662335790110901623740990451586621846212047950084207251595169141015645449217847180683357626383565631317253913942886396494396189837432429078251573229378917400841832190737518763297323901586866664595327850603 c = 14992132140996160330967307558503117255626925777426611978518339050671013041490724616892634911030918360867974894371539160853827180596100892180735770688723270765387697604426715670445270819626709364566478781273676115921657967761494619448095207169386364541164659123273236874649888236433399127407801843412677293516986398190165291102109310458304626261648346825196743539220198199366711858135271877662410355585767124059539217274691606825103355310348607611233052725805236763220343249873849646219850954945346791015858261715967952461021650307307454434510851869862964236227932964442289459508441345652423088404453536608812799355469 hint = int (binascii.hexlify(hint), 16 ) assert (q1p * q1q = = n) assert (q1p<q1q) assert (c = = pow (hint,e,n)) |
一个常规的rsa加密,没有明显的缺陷,尝试分解n
1 | factordb n |
得到两个质数
1 2 | q1p = 127587319253436643569312142058559706815497211661083866592534217079310497260365307426095661281103710042392775453866174657404985539066741684196020137840472950102380232067786400322600902938984916355631714439668326671310160916766472897536055371474076089779472372913037040153356437528808922911484049460342088834871 q1q = 127587319253436643569312142058559706815497211661083866592534217079310497260365307426095661281103710042392775453866174657404985539066741684196020137840472950102380232067786400322600902938984916355631714439668326671310160916766472897536055371474076089779472372913037040153356437528808922911484049460342088835693 |
常规的分解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/usr/bin/python import gmpy2 e = 46531 n = 16278524034278364842964386062476113517067911891699789991355982121084973951738324063305190630865511554888330215827724887964565979607808294168282995825864982603759381323048907814961279012375346497781046417204954101076457350988751188332353062731641153547102721113593787978587135707313755661153376485647168543680503160420091693269984008764444291289486805840439906620313162344057956594836197521501755378387944609246120662335790110901623740990451586621846212047950084207251595169141015645449217847180683357626383565631317253913942886396494396189837432429078251573229378917400841832190737518763297323901586866664595327850603 q = 127587319253436643569312142058559706815497211661083866592534217079310497260365307426095661281103710042392775453866174657404985539066741684196020137840472950102380232067786400322600902938984916355631714439668326671310160916766472897536055371474076089779472372913037040153356437528808922911484049460342088834871 p = 127587319253436643569312142058559706815497211661083866592534217079310497260365307426095661281103710042392775453866174657404985539066741684196020137840472950102380232067786400322600902938984916355631714439668326671310160916766472897536055371474076089779472372913037040153356437528808922911484049460342088835693 c = 14992132140996160330967307558503117255626925777426611978518339050671013041490724616892634911030918360867974894371539160853827180596100892180735770688723270765387697604426715670445270819626709364566478781273676115921657967761494619448095207169386364541164659123273236874649888236433399127407801843412677293516986398190165291102109310458304626261648346825196743539220198199366711858135271877662410355585767124059539217274691606825103355310348607611233052725805236763220343249873849646219850954945346791015858261715967952461021650307307454434510851869862964236227932964442289459508441345652423088404453536608812799355469 assert p * q = = n phi = (p - 1 ) * (q - 1 ) d = gmpy2.invert(e,phi) m = gmpy2.powmod(c,d,n) if q < p : print (q) else : print (p) |
得到完全没用的hint,但是得到了对第三步很有用的q1
3.解得flag
1 2 3 4 5 6 7 | flag = int (binascii.hexlify(flag), 16 ) q1 = q1p q2 = 114401188227479584680884046151299704656920536168767132916589182357583461053336386996123783294932566567773695426689447410311969456458574731187512974868297092638677515283584994416382872450167046416573472658841627690987228528798356894803559278308702635288537653192098514966089168123710854679638671424978221959513 c1 = 262739975753930281690942784321252339035906196846340713237510382364557685379543498765074448825799342194332681181129770046075018122033421983227887719610112028230603166527303021036386350781414447347150383783816869784006598225583375458609586450854602862569022571672049158809874763812834044257419199631217527367046624888837755311215081173386523806086783266198390289097231168172692326653657393522561741947951887577156666663584249108899327053951891486355179939770150550995812478327735917006194574412518819299303783243886962455399783601229227718787081785391010424030509937403600351414176138124705168002288620664809270046124 c2 = 7395591129228876649030819616685821899204832684995757724924450812977470787822266387122334722132760470911599176362617225218345404468270014548817267727669872896838106451520392806497466576907063295603746660003188440170919490157250829308173310715318925771643105064882620746171266499859049038016902162599261409050907140823352990750298239508355767238575709803167676810456559665476121149766947851911064706646506705397091626648713684511780456955453552020460909638016134124590438425738826828694773960514221910109473941451471431637903182205738738109429736425025621308300895473186381826756650667842656050416299166317372707709596 assert (c1 = = pow (flag,e1,p * q1)) assert (c2 = = pow (flag,e2,p * q2)) |
乍一看似乎很简单,连n都已经分解好了(这让我想起了NCTF的easyRSA)
一测试,果然gcd(e1,phi1) == gcd(e2,phi2) == 14
既然到这里了,就总结一下e和phi不互素时的解法(下次)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #!/usr/bin/python import gmpy2 import math from Crypto.Util.number import long_to_bytes from functools import reduce e1 = 15218928658178 e2 = 381791429275130 q1 = 127587319253436643569312142058559706815497211661083866592534217079310497260365307426095661281103710042392775453866174657404985539066741684196020137840472950102380232067786400322600902938984916355631714439668326671310160916766472897536055371474076089779472372913037040153356437528808922911484049460342088834871 p = 109935857933867829728985398563235455481120300859311421762540858762721955038310117609456763338082237907005937380873151279351831600225270995344096532750271070807051984097524900957809427861441436796934012393707770012556604479065826879107677002380580866325868240270494148512743861326447181476633546419262340100453 q2 = 114401188227479584680884046151299704656920536168767132916589182357583461053336386996123783294932566567773695426689447410311969456458574731187512974868297092638677515283584994416382872450167046416573472658841627690987228528798356894803559278308702635288537653192098514966089168123710854679638671424978221959513 c1 = 262739975753930281690942784321252339035906196846340713237510382364557685379543498765074448825799342194332681181129770046075018122033421983227887719610112028230603166527303021036386350781414447347150383783816869784006598225583375458609586450854602862569022571672049158809874763812834044257419199631217527367046624888837755311215081173386523806086783266198390289097231168172692326653657393522561741947951887577156666663584249108899327053951891486355179939770150550995812478327735917006194574412518819299303783243886962455399783601229227718787081785391010424030509937403600351414176138124705168002288620664809270046124 c2 = 7395591129228876649030819616685821899204832684995757724924450812977470787822266387122334722132760470911599176362617225218345404468270014548817267727669872896838106451520392806497466576907063295603746660003188440170919490157250829308173310715318925771643105064882620746171266499859049038016902162599261409050907140823352990750298239508355767238575709803167676810456559665476121149766947851911064706646506705397091626648713684511780456955453552020460909638016134124590438425738826828694773960514221910109473941451471431637903182205738738109429736425025621308300895473186381826756650667842656050416299166317372707709596 def CRT(items): #中国剩余定理 N = reduce ( lambda x, y: x * y, (i[ 1 ] for i in items)) result = 0 for a, n in items: m = N / / n d, r, s = gmpy2.gcdext(n, m) if d ! = 1 : raise Exception( "Input not pairwise co-prime" ) result + = a * s * m return result % N, N tmp = 14 phi1 = (p - 1 ) * (q1 - 1 ) phi2 = (p - 1 ) * (q2 - 1 ) e1 = e1 / / tmp e2 = e2 / / tmp d1 = gmpy2.invert(e1,phi1) d2 = gmpy2.invert(e2,phi2) c1 = gmpy2.powmod(c1,d1,p * q1) % q1 c2 = gmpy2.powmod(c2,d2,p * q2) % q2 n = [q1,q2] c = [c1,c2] data = list ( zip (c,n)) last = CRT(data) e = 7 phi = (q1 - 1 ) * (q2 - 1 ) d = gmpy2.invert(e,phi) m = gmpy2.powmod(last[ 0 ],d,last[ 1 ]) m = gmpy2.iroot(m, 2 )[ 0 ] print (long_to_bytes(m)) |
2. [QCTF2018]Xman-RSA
题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | gqhb jbkl2 pbkhqw pt_kqpbd gqhb ht pbkhqw zqreahb pbkhqw urtd64 adg ulwdt_wh_ezb(u): qdwzqe pew(u.dexhad( 'mdi' ), 16 ) adg ezb_wh_ulwdt(e): u = mdi(e)[ 2 : - 1 ] u = '0' + u pg yde(u) % 2 = = 1 dytd u qdwzqe u.adxhad( 'mdi' ) adg jdw_r_kqpbd(y): qreahb_tdda = zqreahb(y) ezb = ulwdt_wh_ezb(qreahb_tdda) fmpyd Tqzd: pg pt_kqpbd(ezb): uqdrv ezb + = 1 qdwzqe ezb adg dexqlkw(t, d, e): k = ulwdt_wh_ezb(t) k = khf(k, d, e) qdwzqe ezb_wh_ulwdt(k).dexhad( 'mdi' ) adg tdkrqrwd(e): k = e % 4 w = (k * k) % 4 qdwzqe w = = 1 g = hkde( 'gyrj.wiw' , 'q' ) gyrj = g.qdra() btj1 = "" btj2 = "" ghq p pe qrejd(yde(gyrj)): pg tdkrqrwd(p): btj2 + = gyrj[p] dytd: btj1 + = gyrj[p] k1 = jdw_r_kqpbd( 128 ) k2 = jdw_r_kqpbd( 128 ) k3 = jdw_r_kqpbd( 128 ) e1 = k1 * k2 e2 = k1 * k3 d = 0i1001 x1 = dexqlkw(btj1, d, e1) x2 = dexqlkw(btj2, d, e2) kqpew(x1) kqpew(x2) d1 = 0i1001 d2 = 0i101 k4 = jdw_r_kqpbd( 128 ) k5 = jdw_r_kqpbd( 128 ) e3 = k4 * k5 x1 = ezb_wh_ulwdt(khf(e1, d1, e3)).dexhad( 'mdi' ) x2 = ezb_wh_ulwdt(khf(e1, d2, e3)).dexhad( 'mdi' ) kqpew(x1) kqpew(x2) kqpew(urtd64.u64dexhad(ezb_wh_ulwdt(e2))) kqpew(urtd64.u64dexhad(ezb_wh_ulwdt(e3))) |
解题:
从密文形式可以看出是用的python编写的加密脚本,不过这个脚本又被再次加密,猜想应该是纺射加密,从中挑选了两端话来对比得出a和b
1 2 | gqhb jbkl2 pbkhqw from xxxxx import |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/python #-------------data--------------- # # c : 6 16 7 1 -2 15 1 10 7 16 22 # m : 5 17 14 12 -2 8 12 15 14 17 19 #---------get encode a and b--------- for a in range ( 30 ): for b in range ( 30 ): if (a * 5 + b) % 26 = = 6 : if ( 17 * a + b) % 26 = = 16 : if ( 14 * a + b) % 26 = = 7 : print (a) print (b) |
得出a = 3, b = 17
纺射解密后得到加密脚本,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | from gmpy2 import is_prime from os import urandom import base64 def bytes_to_num(b): return int (b.encode( 'hex' ), 16 ) def num_to_bytes(n): b = hex (n)[ 2 : - 1 ] b = '0' + b if len (b) % 2 = = 1 else return b.decode( 'hex' ) def get_a_prime(l): random_seed = urandom(l) num = bytes_to_num(random_seed) while True : if is_prime(num): break num + = 1 return num def encrypt(s, e, n): p = bytes_to_num(s) p = pow (p, e, n) return num_to_bytes(p).encode( 'hex' ) def separate(n): p = n % 4 t = (p * p) % 4 return t = = 1 f = open ( 'flag.txt' , 'r' ) flag = f.read() msg1 = "" msg2 = "" for i in range ( len (flag)): if separate(i): msg2 + = flag[i] else : msg1 + = flag[i] p1 = get_a_prime( 128 ) p2 = get_a_prime( 128 ) p3 = get_a_prime( 128 ) n1 = p1 * p2 n2 = p1 * p3 e = 0x1001 c1 = encrypt(msg1, e, n1) c2 = encrypt(msg2, e, n2) print (c1) print (c2) e1 = 0x1001 e2 = 0x101 p4 = get_a_prime( 128 ) p5 = get_a_prime( 128 ) n3 = p4 * p5 c1 = num_to_bytes( pow (n1, e1, n3)).encode( 'hex' ) c2 = num_to_bytes( pow (n1, e2, n3)).encode( 'hex' ) print (c1) print (c2) print (base64.b64encode(num_to_bytes(n2))) print (base64.b64encode(num_to_bytes(n3))) |
进入了rsa解题过程,我们先看最后一个加密,相同的明文,相同的n,不同的e
用共模攻击解出n1来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/python2 #coding:utf-8 import gmpy2 from Crypto.Util.number import long_to_bytes e1 = 0x1001 e2 = 0x101 n = 9895571060693703887018268413746107679094703478067972087862851570192520012058188062485476484700707994684397704099884436398099581319015589480235346899990863625919087077906193223937343450727301243043576326163300258770936289423785376338765758863453745278516208013244068358484113062931878984339475569902332075509121153749576470546863477142562563573654198332099438611713385318497180237117792417826080724886477023904678472464557511959911739272258202310963925049222305927992349171516332320267610895787011879250778522843808895509894741144901052000573058315131265960606119769594234837973757057319170067823816025499647517874841 c1 = 0x2639c28e3609a4a8c953cca9c326e8e062756305ae8aee6efcd346458aade3ee8c2106ab9dfe5f470804f366af738aa493fd2dc26cb249a922e121287f3eddec0ed8dea89747dc57aed7cd2089d75c23a69bf601f490a64f73f6a583081ae3a7ed52238c13a95d3322065adba9053ee5b12f1de1873dbad9fbf4a50a2f58088df0fddfe2ed8ca1118c81268c8c0fd5572494276f4e48b5eb424f116e6f5e9d66da1b6b3a8f102539b690c1636e82906a46f3c5434d5b04ed7938861f8d453908970eccef07bf13f723d6fdd26a61be8b9462d0ddfbedc91886df194ea022e56c1780aa6c76b9f1c7d5ea743dc75cec3c805324e90ea577fa396a1effdafa3090 c2 = 0x42ff1157363d9cd10da64eb4382b6457ebb740dbef40ade9b24a174d0145adaa0115d86aa2fc2a41257f2b62486eaebb655925dac78dd8d13ab405aef5b8b8f9830094c712193500db49fb801e1368c73f88f6d8533c99c8e7259f8b9d1c926c47215ed327114f235ba8c873af7a0052aa2d32c52880db55c5615e5a1793b690c37efdd5e503f717bb8de716303e4d6c4116f62d81be852c5d36ef282a958d8c82cf3b458dcc8191dcc7b490f227d1562b1d57fbcf7bf4b78a5d90cd385fd79c8ca4688e7d62b3204aeaf9692ba4d4e44875eaa63642775846434f9ce51d138ca702d907849823b1e86896e4ea6223f93fae68b026cfe5fa5a665569a9e3948a _, r, s = gmpy2.gcdext(e1, e2) m = pow (c1, r, n) * pow (c2, s, n) % n print m |
对于倒数第二段加密,通过这两句代码
1 2 | n1 = p1 * p2 n2 = p1 * p3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/usr/bin/python import gmpy2 from Crypto.Util.number import long_to_bytes,isPrime n1 = 2499586809914462821807624371088011200618603528498132509598946284572455726453497171635086810524607288333625665025664872216634366700044105279185519761587818169021167370991396691510275499486673922916370294043072503635630922980240462022218565365191228535222150496387990987123639567257124081274667568443678527637259644488779394704508217357758791670308548246801142468699716221789070607334747835552167450340441488756779323653879402176647890584656379628685893686585469918686253137796663587854943386347039389769790329948165162483370187914412810153613198247569427480466488647563900948387020677830797976534568626241686906738179 n2 = 7741603029707932330739678982394275613217057249691533148704382574439895657047911501600910571360188397109729289277796711334388156202412769743785164713243932001078475541271281825859671767783178037363138683152051263779907568124470598237502689045677891605285193637790880045372303913424654655825837641694318544209980415256180296972066060073206323473960669679401950151966003026531573962072358852304635671658878866030003484715256388556599713638695448516673643703041094737763957937855870992247472296348887788212823714735080211059688680618314050267995177478035769912691185787944037050674163079867101586607780761245261558200843 n3 = 9895571060693703887018268413746107679094703478067972087862851570192520012058188062485476484700707994684397704099884436398099581319015589480235346899990863625919087077906193223937343450727301243043576326163300258770936289423785376338765758863453745278516208013244068358484113062931878984339475569902332075509121153749576470546863477142562563573654198332099438611713385318497180237117792417826080724886477023904678472464557511959911739272258202310963925049222305927992349171516332320267610895787011879250778522843808895509894741144901052000573058315131265960606119769594234837973757057319170067823816025499647517874841 c1 = 0x1240198b148089290e375b999569f0d53c32d356b2e95f5acee070f016b3bef243d0b5e46d9ad7aa7dfe2f21bda920d0ac7ce7b1e48f22b2de410c6f391ce7c4347c65ffc9704ecb3068005e9f35cbbb7b27e0f7a18f4f42ae572d77aaa3ee189418d6a07bab7d93beaa365c98349d8599eb68d21313795f380f05f5b3dfdc6272635ede1f83d308c0fdb2baf444b9ee138132d0d532c3c7e60efb25b9bf9cb62dba9833aa3706344229bd6045f0877661a073b6deef2763452d0ad7ab3404ba494b93fd6dfdf4c28e4fe83a72884a99ddf15ca030ace978f2da87b79b4f504f1d15b5b96c654f6cd5179b72ed5f84d3a16a8f0d5bf6774e7fd98d27bf3c9839 c2 = 0x129d5d4ab3f9e8017d4e6761702467bbeb1b884b6c4f8ff397d078a8c41186a3d52977fa2307d5b6a0ad01fedfc3ba7b70f776ba3790a43444fb954e5afd64b1a3abeb6507cf70a5eb44678a886adf81cb4848a35afb4db7cd7818f566c7e6e2911f5ababdbdd2d4ff9825827e58d48d5466e021a64599b3e867840c07e29582961f81643df07f678a61a9f9027ebd34094e272dfbdc4619fa0ac60f0189af785df77e7ec784e086cf692a7bf7113a7fb8446a65efa8b431c6f72c14bcfa49c9b491fb1d87f2570059e0f13166a85bb555b40549f45f04bc5dbd09d8b858a5382be6497d88197ffb86381085756365bd757ec3cdfa8a77ba1728ec2de596c5ab p1 = gmpy2.gcd(n1,n2) p2 = n1 / / p1 p3 = n2 / / p1 assert isPrime(p1) assert isPrime(p2) assert isPrime(p3) e = 0x1001 phi1 = (p1 - 1 ) * (p2 - 1 ) phi2 = (p1 - 1 ) * (p3 - 1 ) d1 = gmpy2.invert(e,phi1) d2 = gmpy2.invert(e,phi2) m1 = gmpy2.powmod(c1,d1,n1) m2 = gmpy2.powmod(c2,d2,n2) print (long_to_bytes(m1)) print (long_to_bytes(m2)) |
解出两组明文,最后通过栅栏解密得到flag
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
|
|
---|---|
|
大佬,关于p-adic 和随机数生成器有啥好的教程或者书籍推荐吗
|
|
happi0师傅,写得好详细,学到了许多,以后记得多多写相关的文章,学学新姿势。。。。:)
|
|
mark,学到了很多,感谢感谢,希望能够看到更多类似的文章
|
|
大佬写的好详细呀
|
|
八岛 大佬,关于p-adic 和随机数生成器有啥好的教程或者书籍推荐吗《密码学随机数发生器的设计与分析》,这本书不错 |
|
|