RSA 数字签名

原理

原理类似于 RSA 加密,只是这里使用私钥进行加密,将加密后的结果作为签名。

2018 Backdoor Awesome mix1

首先,可以简单分析源码,这里程序使用 PKCS1_V1.5 进行了 RSA 签名,这会对明文消息进行扩展,具体扩展规则请参考 https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf 。这里给出对应扩展脚本,对应于题目中的 from Util import PKCS1_pad as pad

def PKCS1_pad(data):
    asn1 = "3021300906052b0e03021a05000414"
    ans = asn1 + data
    n = len(ans)
    return int(('00' + '01' + 'ff' * (1024 / 8 - n / 2 - 3) + '00' + ans), 16)

程序希望我们给出 n,e 使得程序满足

$h(m)^e mod \ n=pad(m)$

这里我们已经知道 h(m),pad(m)。显然如果我们控制 e=1的话,那么

$h(m)-pad(m)=kn$

那么如果我们可以设置 k=1,既可以得到 n。

本地部署 socat TCP4-LISTEN:12345,fork EXEC:./mix1.py

exp 如下

效果如下

2018 Backdoor Awesome mix2

本地部署 socat TCP4-LISTEN:12345,fork EXEC:./service.py

题目类似于上面的题目,唯一的区别在于对于 e 有约束,必须大于 3,所以我们不能使用 1 了。

$h(m)^e mod \ n=pad(m)$

这里我们已经知道 h(m),pad(m)。我们只需要构造剩下的数即可,这里我们构造 n 为素数,使得 n-1是一个光滑数,这样就可以使用 pohlig_hellman 算法了。

有两点需要注意

  1. 由于 $g^x=y$ 中的 g 和 y 都是给定的,我们新找到的 n,不一定 g 的幂次构成的群会包含 y,所以可能求解失败,所以需要多次求解。

  2. 源代码中虽然 n.bit_length() <= 1025,但是其实 n 在满足不小于 signature 的条件时,必须满足如下条件(pycrypto 源码)

所以我们最好设置 n 为1024 比特位。

Last updated