RSA由密文解密的奇偶性确定原始明文

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=c2e(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 c1c02e(modn)m1c1d(modn)m1m0cd2ed(modn)m1m02(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 (c02e)d=2m0>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 m12m0(modn)等价于 2 ⋅ m 0 − n 2\cdot m_0-n 2m0n;而由于一般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 2m0<n的情况区别开来了(该情况的结果是模n之后等于偶数even

这样区别开来的作用是

当传入 c 1 ≡ c 0 ⋅ 2 e ( m o d n ) c_1\equiv c_0 \cdot 2^e\pmod n c1c02e(modn)的结果 c 1 c_1 c1之后,服务端返回结果为odd,那么意味着, n < 2 ⋅ m 0 < 2 ⋅ n n<2\cdot m_0<2\cdot n n<2m0<2n,也就意味这 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 c1c02e(modn)的结果 c 1 c_1 c1之后,服务端返回结果为even,那么意味着, 0 < 2 ⋅ m 0 < n 0<2\cdot m_0<n 0<2m0<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 c2c12e(modn),解密之后也就等价于 4 ⋅ m 0 4\cdot m_0 4m0,继续判断奇偶性就可以进一步缩小原始明文 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解密函数,代码会更简洁一些

R e f e r e n c e Reference Reference

QCTF 2018线上赛 writeup - 蝉时雨 - 博客园 (cnblogs.com)

XCTF-4th-QCTF-2018-babyrsa - 芒果的小站 (mangofeng.cn)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

M3ng@L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值