RSA由密文解密的奇偶性确定原始明文
k
e
y
w
o
r
d
s
:
keywords:
keywords: XCTF 4th-QCTF-2018-babyrsa
P r o b l m e Problme Problme
'''
Baby RSA
e = 0x10001
n = 0x0b765daa79117afe1a77da7ff8122872bbcbddb322bb078fe0786dc40c9033fadd639adc48c3f2627fb7cb59bb0658707fe516967464439bdec2d6479fa3745f57c0a5ca255812f0884978b2a8aaeb750e0228cbe28a1e5a63bf0309b32a577eecea66f7610a9a4e720649129e9dc2115db9d4f34dc17f8b0806213c035e22f2c5054ae584b440def00afbccd458d020cae5fd1138be6507bc0b1a10da7e75def484c5fc1fcb13d11be691670cf38b487de9c4bde6c2c689be5adab08b486599b619a0790c0b2d70c9c461346966bcbae53c5007d0146fc520fa6e3106fbfc89905220778870a7119831c17f98628563ca020652d18d72203529a784ca73716db
c = 0x4f377296a19b3a25078d614e1c92ff632d3e3ded772c4445b75e468a9405de05d15c77532964120ae11f8655b68a630607df0568a7439bc694486ae50b5c0c8507e5eecdea4654eeff3e75fb8396e505a36b0af40bd5011990663a7655b91c9e6ed2d770525e4698dec9455db17db38fa4b99b53438b9e09000187949327980ca903d0eef114afc42b771657ea5458a4cb399212e943d139b7ceb6d5721f546b75cd53d65e025f4df7eb8637152ecbb6725962c7f66b714556d754f41555c691a34a798515f1e2a69c129047cb29a9eef466c206a7f4dbc2cea1a46a39ad3349a7db56c1c997dc181b1afcb76fa1bbbf118a4ab5c515e274ab2250dba1872be0
'''
提供了nc
链接地址,简单把c
传入得到
C:\Users\Menglin>nc 111.200.241.244 62431
----------------------------- baby rsa -----------------------------
Come and Decode your data
If you give me ciphertext, I can tell you whether decoded data is even or odd
You can input ciphertext(hexdecimal) now
0x4f377296a19b3a25078d614e1c92ff632d3e3ded772c4445b75e468a9405de05d15c77532964120ae11f8655b68a630607df0568a7439bc694486ae50b5c0c8507e5eecdea4654eeff3e75fb8396e505a36b0af40bd5011990663a7655b91c9e6ed2d770525e4698dec9455db17db38fa4b99b53438b9e09000187949327980ca903d0eef114afc42b771657ea5458a4cb399212e943d139b7ceb6d5721f546b75cd53d65e025f4df7eb8637152ecbb6725962c7f66b714556d754f41555c691a34a798515f1e2a69c129047cb29a9eef466c206a7f4dbc2cea1a46a39ad3349a7db56c1c997dc181b1afcb76fa1bbbf118a4ab5c515e274ab2250dba1872be0
odd
A n a l y s i s Analysis Analysis
提供的n,c,e
是正常的RSA的公钥以及密文;那么突破重点便是nc
链接服务端的作用
If you give me ciphertext, I can tell you whether decoded data is even or odd
以上是服务端脚本的作用解释,其作用就是把使用本题中的(n,e)
作为公钥生成的密文解密得到的数值判断奇偶性并返回
但是这里关于(n,e)
生成的密文只有c
,我们怎么使用这个条件呢
在模n
的条件下改变c
的大小,并且能够改变其奇偶性:
c
=
c
⋅
2
e
(
m
o
d
n
)
c=c\cdot 2^e\pmod n
c=c⋅2e(modn)
上述等式的作用是解出的明文相当于原来明文的两倍
c
1
≡
c
0
⋅
2
e
(
m
o
d
n
)
m
1
≡
c
1
d
(
m
o
d
n
)
⇒
m
1
≡
m
0
c
⋅
d
⋅
2
e
⋅
d
(
m
o
d
n
)
⇒
m
1
≡
m
0
⋅
2
(
m
o
d
n
)
c_1\equiv c_0\cdot 2^e\pmod n\\ m_1 \equiv c_1^d \pmod n\\ \Rightarrow m_1 \equiv m_0^{c\cdot d}\cdot 2^{e\cdot d}\pmod n\\ \Rightarrow m_1\equiv m_0 \cdot 2\pmod n
c1≡c0⋅2e(modn)m1≡c1d(modn)⇒m1≡m0c⋅d⋅2e⋅d(modn)⇒m1≡m0⋅2(modn)
而我们可以发现原来的c
解密之后明文flag
奇偶性为odd
,即为奇数
如果奇数乘以
2
2
2,结果一定为偶数;但是如果是在模
n
n
n的情况下则不一定,当
(
c
0
⋅
2
e
)
d
=
2
⋅
m
0
>
n
(c_0\cdot 2^e)^d=2\cdot m_0>n
(c0⋅2e)d=2⋅m0>n,首先由于
0
<
c
0
<
n
0<c_0<n
0<c0<n,那么最后返回的
m
1
≡
2
⋅
m
0
(
m
o
d
n
)
m_1\equiv 2\cdot m_0\pmod n
m1≡2⋅m0(modn)等价于
2
⋅
m
0
−
n
2\cdot m_0-n
2⋅m0−n;而由于一般RSA的
n
n
n是由两个大素数相乘生成的(只要是素数相乘都一样),所以
n
n
n必定是奇数,原来的
m
0
m_0
m0乘以
2
2
2等于一个偶数even
,当ta减去一个奇数之后结果等于奇数,这样就与
2
⋅
m
0
<
n
2\cdot m_0<n
2⋅m0<n的情况区别开来了(该情况的结果是模n
之后等于偶数even
)
这样区别开来的作用是
当传入
c
1
≡
c
0
⋅
2
e
(
m
o
d
n
)
c_1\equiv c_0 \cdot 2^e\pmod n
c1≡c0⋅2e(modn)的结果
c
1
c_1
c1之后,服务端返回结果为odd
,那么意味着,
n
<
2
⋅
m
0
<
2
⋅
n
n<2\cdot m_0<2\cdot n
n<2⋅m0<2⋅n,也就意味这
n
2
<
m
0
<
n
\frac{n}{2}<m_0<n
2n<m0<n;这样就缩小了原始明文
m
0
m_0
m0的大小范围
当传入
c
1
≡
c
0
⋅
2
e
(
m
o
d
n
)
c_1\equiv c_0 \cdot 2^e\pmod n
c1≡c0⋅2e(modn)的结果
c
1
c_1
c1之后,服务端返回结果为even
,那么意味着,
0
<
2
⋅
m
0
<
n
0<2\cdot m_0<n
0<2⋅m0<n,等价于
0
<
m
0
<
n
2
0<m_0<\frac{n}{2}
0<m0<2n;同样也缩小了原始明文
m
0
m_0
m0的大小范围
当计算完 c 1 c_1 c1之后,在 c 1 c_1 c1的基础上继续进行 c 2 ≡ c 1 ⋅ 2 e ( m o d n ) c_2\equiv c_1 \cdot 2^e\pmod n c2≡c1⋅2e(modn),解密之后也就等价于 4 ⋅ m 0 4\cdot m_0 4⋅m0,继续判断奇偶性就可以进一步缩小原始明文 m 0 m_0 m0的大小范围;以此类推,最后将原始明文的大小范围缩小到只有一个值,那么便是原始明文的值
并且缩小的范围相当于 u p p e r + l o w e r 2 \frac{upper+lower}{2} 2upper+lower
注意一点是这里服务端的脚本将传入的数值进行了转换,可能是这样的
input = int(input,16)
那么就意味着传入的数值c
必须是hex
十六进制形式的
怎么看出来的呢?因为
>>>int("0x4f377296a19b3a25078d614e1c92ff632d3e3ded772c4445b75e468a9405de05d15c77532964120ae11f8655b68a630607df0568a7439bc694486ae50b5c0c8507e5eecdea4654eeff3e75fb8396e505a36b0af40bd5011990663a7655b91c9e6ed2d770525e4698dec9455db17db38fa4b99b53438b9e09000187949327980ca903d0eef114afc42b771657ea5458a4cb399212e943d139b7ceb6d5721f546b75cd53d65e025f4df7eb8637152ecbb6725962c7f66b714556d754f41555c691a34a798515f1e2a69c129047cb29a9eef466c206a7f4dbc2cea1a46a39ad3349a7db56c1c997dc181b1afcb76fa1bbbf118a4ab5c515e274ab2250dba1872be0",16)
10000168328337586723723875929199426704755546201195615734523254693814039765906148543232611129765509088000736956851520022537085658495744583517648184152998168309758485546037306528320166722634787751788563573939958617061265638476529095277032847794703409537505203594204567151328850116513909550356213958708966751554276850944050261394701167302379584172517413175668997227366580985191901168830374739189734903482208079680206788635600160218616793118994764212910484101984483101655772133593536065667175866557356425850372486695596296455668658676150338420608042931515767744544733279970819343643596659567320755262783035393928843439072
---
C:\Users\Menglin>nc 111.200.241.244 62431
----------------------------- baby rsa -----------------------------
Come and Decode your data
If you give me ciphertext, I can tell you whether decoded data is even or odd
You can input ciphertext(hexdecimal) now
10000168328337586723723875929199426704755546201195615734523254693814039765906148543232611129765509088000736956851520022537085658495744583517648184152998168309758485546037306528320166722634787751788563573939958617061265638476529095277032847794703409537505203594204567151328850116513909550356213958708966751554276850944050261394701167302379584172517413175668997227366580985191901168830374739189734903482208079680206788635600160218616793118994764212910484101984483101655772133593536065667175866557356425850372486695596296455668658676150338420608042931515767744544733279970819343643596659567320755262783035393928843439072
even
得到的结果与传入十六进制时不同,所以得到上述结果
而Python会自动把十六进制转换为十进制再进行进一步操作,所以最后上传时需要再一次手动转换十六进制才行
>>> c = 0x4f377296a19b3a25078d614e1c92ff632d3e3ded772c4445b75e468a9405de05d15c77532964120ae11f8655b68a630607df0568a7439bc694486ae50b5c0c8507e5eecdea4654eeff3e75fb8396e505a36b0af40bd5011990663a7655b91c9e6ed2d770525e4698dec9455db17db38fa4b99b53438b9e09000187949327980ca903d0eef114afc42b771657ea5458a4cb399212e943d139b7ceb6d5721f546b75cd53d65e025f4df7eb8637152ecbb6725962c7f66b714556d754f41555c691a34a798515f1e2a69c129047cb29a9eef466c206a7f4dbc2cea1a46a39ad3349a7db56c1c997dc181b1afcb76fa1bbbf118a4ab5c515e274ab2250dba1872be0
>>> c
10000168328337586723723875929199426704755546201195615734523254693814039765906148543232611129765509088000736956851520022537085658495744583517648184152998168309758485546037306528320166722634787751788563573939958617061265638476529095277032847794703409537505203594204567151328850116513909550356213958708966751554276850944050261394701167302379584172517413175668997227366580985191901168830374739189734903482208079680206788635600160218616793118994764212910484101984483101655772133593536065667175866557356425850372486695596296455668658676150338420608042931515767744544733279970819343643596659567320755262783035393928843439072
所以我们需要
c = 0x...
io.sendline(hex(c))
另外由于时常有网络波动(本题需要不断重复链接服务端),所以加入了try,except
语句保证因为网络波动断开了连接之后继续进行连接计算
S o l v i n g c o d e Solving~code Solving code
from Crypto.Util.number import *
import gmpy2
from pwn import *
e = 0x10001
n = 0x0b765daa79117afe1a77da7ff8122872bbcbddb322bb078fe0786dc40c9033fadd639adc48c3f2627fb7cb59bb0658707fe516967464439bdec2d6479fa3745f57c0a5ca255812f0884978b2a8aaeb750e0228cbe28a1e5a63bf0309b32a577eecea66f7610a9a4e720649129e9dc2115db9d4f34dc17f8b0806213c035e22f2c5054ae584b440def00afbccd458d020cae5fd1138be6507bc0b1a10da7e75def484c5fc1fcb13d11be691670cf38b487de9c4bde6c2c689be5adab08b486599b619a0790c0b2d70c9c461346966bcbae53c5007d0146fc520fa6e3106fbfc89905220778870a7119831c17f98628563ca020652d18d72203529a784ca73716db
c = int("0x4f377296a19b3a25078d614e1c92ff632d3e3ded772c4445b75e468a9405de05d15c77532964120ae11f8655b68a630607df0568a7439bc694486ae50b5c0c8507e5eecdea4654eeff3e75fb8396e505a36b0af40bd5011990663a7655b91c9e6ed2d770525e4698dec9455db17db38fa4b99b53438b9e09000187949327980ca903d0eef114afc42b771657ea5458a4cb399212e943d139b7ceb6d5721f546b75cd53d65e025f4df7eb8637152ecbb6725962c7f66b714556d754f41555c691a34a798515f1e2a69c129047cb29a9eef466c206a7f4dbc2cea1a46a39ad3349a7db56c1c997dc181b1afcb76fa1bbbf118a4ab5c515e274ab2250dba1872be0",16)
m_upper = n
m_lower = 0
while True:
try:
io = remote("111.200.241.244","62431")
io.recvuntil(b"now")
c = (c * pow(2,e,n)) % n
io.sendline(hex(c))
output = io.recvall().strip().decode()
if output == "even":
m_upper = (m_upper + m_lower) // 2
elif output == "odd":
m_lower = (m_upper + m_lower) // 2
print(m_upper)
if m_upper == m_lower:
print(long_to_bytes(m_upper))
print(long_to_bytes(m_lower))
break
except:
io = remote("111.200.241.244","62431")
io.recvuntil(b"now")
c = (c * pow(2,e,n)) % n
io.sendline(hex(c))
output = io.recvall().strip().decode()
if output == "even":
m_upper = (m_upper + m_lower) // 2
elif output == "odd":
m_lower = (m_upper + m_lower) // 2
print(m_upper)
if m_upper == m_lower:
print(long_to_bytes(m_upper))
break
当然也可以def
解密函数,代码会更简洁一些