RSA 的运行过程中,对于一个公钥(n,e),加密过程计算的是明文m 的幂次即memodn,常见的一个e 的取值是 65537 即 0x10001,通过快速幂计算这个过程一般来说还是比较容易的。但是问题在于,私钥指数(n,d) 中的d≡e−1(mod ϕ(n)),这个d 的取值可能是十分大的,相应带来的也就是巨大的解密计算量。这个加解密计算量不对等的问题,对于一些缺少计算能力的嵌入式设备可以说是致命的。
一个加速的思想在于,构造一个比较小的私钥指数d,这样解密的过程可以得到显著的加快。但是这样的构造实际上会破坏 RSA 的安全性。
# 连分数
Wiener 的思路是构造连分数以攻破解密指数。
连分数是下面这样形式的分数:
=q1+q2+...qm−1+qmam...a3a2a1a1/(q1+a2/(q2+a3/(../(qm−1+am/qm)...)))
在 Wiener 的构造中,定义下面的式子为:
==<q0,q1,...,qm>q0+1/(q1+1/(q2+1/(.../(qm−1+1/qm)...)))q0+q1+q2+...qm−1+qm1...111
例如<0,2,1,3>=0+1/(2+1/(1+1/3))=114,在这里称<0,2,1,3> 就是114 的连分数扩展。
通过这样的方式可以将一个整数f 表示成连分数:每一层连分数中,都用qi 表示整数部分(商),用ri 表示剩余部分(余数),带入下一步的连分数中得到ri=qi+1+ri+1:
q0=⌊f⌋,r0=f−q0qi=⌊ri−11⌋,ri=ri−11−qi,i=1,2,3,...,m(1)
这样到rm=0 时,就能够构造出f=<q0,q1,...,qm>。
这边可以注意到最后一项的qm 必定是大于等于 2 的,如果qm=1,那么必定会有rm−1=1,显然这是不可能的,因为ri 表示的是小数部分。
另外需要注意的一个性质是这样的:
对于偶数 m,有:
⟨q0,q1,...,qm⟩<⟨q0,q1,...,qm−1,qm+x⟩,(x>0)(2.1)
而对于奇数 m,则是:
⟨q0,q1,...,qm⟩>⟨q0,q1,...,qm−1,qm+x⟩,(x>0)(2.2)
从直观上理解来说,当最后一位从qm 变为了qm+x 也就是增大了,那么外面一层的分数即qm−1+qm+x1 则会变小,再外面一层则会增大……
完成了连分数的构建,接下来的问题就是怎么样从一个连分数去恢复出原来的数f。
最简单的方法也就是从qm 开始,从最底层向上逐级计算。Wiener 的思路则采用的是一种自顶向下的方法。
构建这样的两个序列ni 和di,其中i=0,1,...,m:
dini=⟨q0,q1,...,qi⟩, gcd(ni,di)=1
这样也就是有(i=2,3,...,m):
n0=q0,n1=q0q1+1,...ni=qini−1+ni−2,d0=1d1=q1di=qidi−1+di−2(3)
这样就可以重建整个连分数对应的f=dmnm 了。
此外,可以通过上面的式子构造得到:
nidi−1−ni−1di=−(−1)i
这会在后面被用到。
# 连分数算法
我们令f′=f⋅(1−δ),δ>0。
如果δ 足够小的话,那么f′ 非常趋近于f,也就可以通过f′ 去求到f。
这里令qi,ri 和qi′ri′ 分别是f 和f′ 按照前面公式 (1) 形式得到的商和余数。我们可以通过这样的方法计算出f:
- 计算f′ 连分数扩展的下一个对应的商qi′。
- 使用上面公式 (3) 构造下面形式的连分数:
⟨q0′,q1′,...,qi′+1⟩,⟨q0′,q1′,...,qi′⟩,if i is even,if i is odd
- 如果上面构造的连分数等于f,那么算法结束,否则继续。
如果f 比f′ 要大,又根据公式 (2.1)(2.2),在i 为奇数,有⟨q0′,q1′,...,qi−1′,qi′⟩<⟨q0′,q1′,...,qi−1′,qi′+ri′,所以说上面的式子中,在奇数的情况下最后一项为qi′+1。
当满足
⟨q0,q1,...,qm−1⟩<f′≤⟨q0,q1,...,qm⟩,⟨q0,q1,...,qm+1⟩<f′≤⟨q0,q1,...,qm−1⟩,if m is even,if m is odd
在这种情况下,这个算法能够成功地求出f。Wiener 求出,对应的情况下δ 的取值满足:
δ<23nmdm1(4)
nm,dm 为满足上文公式 (3) 的构造。这个算法的时间复杂度是O(logx),其中x 为max(nm,dm)。
# RSA
一种 RSA 的构造中,私钥指数的取值是这样的:
ed≡1(mod LCM(p−1,q−1))
也就是存在一个K 满足
ed=K⋅LCM(p−1,q−1)+1
如果G=gcd(p−1,q−1),有LCM(p−1,q−1)=(p−1)(q−1)/G,可以得到
ed=GK(p−1)(q−1)+1
其中K 和G 有比较大的概率是有公因数的,那么我们定义k=K/gcd(K,G),g=G/gcd(K,G),就有k/g=K/G,且gcd(k,g)=1,这样子就会得到:
ed=gk(p−1)(q−1)+1
在等式两边同时除以dpq 能够得到
pqe=dgk(1−δ), δ=pqp+q−1−kg
这条式子可以构造前面连分数的形式。考虑到gcd(K,d)=1,gcd(k,d)=1,gcd(k,g)=1,能够得出,
kdg<23(p+q)pq
这足够能计算出k 和dg。
我们可以假设ed>pq,在这种情况下,有
edg=k(p−1)(q−1)+g
对于k>g,两边同时除以k(k>g) 能够得到(p−1)(q−1) 和一个余数g。如果能够猜测出(p−1)(q−1),那么
2pq−(p−1)(q−1)+1=2p+q
如果上面等式右边不是整数,那么上面的猜测就是错误的。此外又有
(2p+q)2−pq=(2p−q)2
如果等式右边是一个完美平方数,那么猜测就是正确的。从这正确的猜测中就能够得到私钥指数d。
# 参考资料
【1】 M. J. Wiener, "Cryptanalysis of short RSA secret exponents," in IEEE Transactions on Information Theory, vol. 36, no. 3, pp. 553-558, May 1990, doi: 10.1109/18.54902.