记录RSA入门的一些做题笔记
DiceCTF 2022 baby-rsa
1 | def getAnnoyingPrime(nbits, e): |
p,q为128为的素数,在yafu中很快可以分解出来。这题难点在于(p-1) % e^2 == 0和 (q-1) % e^2 == 0,所以d = gmpy2.invert(e, (p-1)*(q-1))会报错。实在不会只能在网上找东西来学习了。
当e较小时可以通过sage 用 GF(p)(c).nth_root(e, all=True)
处理
1 | from Crypto.Util.number import * |
这部分代码执行了解密过程。
GF(p)(c).nth_root(e, all=True)
:这行代码计算了GF(p)
上的c
的e
次方根,并使用all=True
选项获取了所有可能的解。GF(p)
是定义在有限域上的多项式环,这里将其用于计算模p
下的多项式。GF(q)(c).nth_root(e, all=True)
:这行代码计算了GF(q)
上的c
的e
次方根,并使用all=True
选项获取了所有可能的解。GF(q)
是定义在有限域上的多项式环,这里将其用于计算模q
下的多项式。crt([ZZ(mp), ZZ(mq)], [p, q])
:这行代码使用了中国剩余定理(Chinese Remainder Theorem, CRT)。crt
函数接受两个列表作为参数,第一个列表包含两个部分解密值mp
和mq
,第二个列表包含对应的模数p
和q
。它将这些值合并为一个明文值m
。flag = long_to_bytes(m)
:这行代码将解密后的明文m
转换为字节形式。long_to_bytes
函数将长整型数值转换为字节字符串。if flag.startswith(b"dice{"):
:这行代码检查解密出的明文是否以b"dice{"
开头,判断是否解密出了正确的结果。print(flag)
:如果解密出的明文满足条件,则打印出明文结果
Maple CTF 2022 brsaby
1 | from Crypto.Util.number import getPrime, bytes_to_long |
由题目可知hint=p^4-q^3,p,q都是512位的素数,所以p,q很接近所以hint约等于(p-1)*p^3约等于p^4
所以在sage中跑出p,q
1 | from sage.all import * |
这里本以为不会刚刚好得到p,q但是经过检验发现这里的确就是p,q的值。
因为对sage不够熟悉,所以还是在python中拿到flag
1 | from Crypto.Util.number import long_to_bytes, isPrime |
TSGCTF 2021 Beginner’s Crypto 2021
题目源码
1 | from secret import e |
1 | from math import gcd |
在RSA加密算法中,密文 c
是通过对明文 m
进行指数幂运算并取模 N
得到的。即,c ≡ m^e (mod N)
。
解密过程就是要找到明文 m
,使得 m^e ≡ c (mod N)
成立。
根据扩展欧几里得算法的性质,如果 (x, y)
是 e
和 (p-1)*(q-1)
的贝祖等式的解,那么 (m^e)^x ≡ m^(e*x) ≡ m^(k*(p-1)*(q-1)+1) ≡ m (mod N)
,其中 k
是一个整数。
因此,我们可以使用 (m^e)^x ≡ c^x (mod N)
的方式,通过计算 c^x (mod N)
来还原明文 m
。
具体到代码中的步骤,通过计算 pow(c1, x, N)
和 pow(c2, y, N)
,我们分别得到了 c1^x (mod N)
和 c2^y (mod N)
。然后,通过乘法操作 pow(c1, x, N) * pow(c2, y, N) % N
,我们得到了 m^e ≡ c1^x * c2^y ≡ (m^x)^e * (m^y)^e ≡ m (mod N)
。
因此,通过对密文 c1
和 c2
进行模 N
的幂运算,并通过乘法和模运算得到明文的整数表示 m
,就实现了RSA解密过程。
m.to_bytes((m.bit_length() + 7) // 8, 'big')
是将整数 m
转换为字节串形式的表达式。
让我们逐步解释这段代码:
m.bit_length()
返回整数m
的位数,即表示m
所需的二进制位数。+ 7
是为了确保在整数位数不是8的倍数的情况下,对字节长度进行向上取整。// 8
将位数转换为字节数,因为1个字节等于8个位。'big'
是一个参数,指示生成的字节串的字节顺序。在这里,'big'
表示使用大端字节顺序,即高位字节排在前面。
因此,m.to_bytes((m.bit_length() + 7) // 8, 'big')
将整数 m
转换为一个字节串,以便以字节形式表示明文。这样可以将明文从整数形式转换为可读的字节串形式,方便查看和处理。
题解都是问gpt的,原理啥的也都一知半解的,这个就当个备份,以后看见相似的题目往上套一下试试。