中国剩余定理CRT
CRT
简介
设p和q是不同的质数,且n = p*q。对于任意(X1, x2),其中 0 ≤ x1 < p 和 0 ≤ x2 < q,存在数x,其中 0 ≤ x < n。 在RSA中我们会拿到两个式子。
m1=cd mod p
m2=cd mod q
如果m比模数小的话,我们可以正确解密。如果m比模大则无法正确解密,此时我们需要扩大模数。
接下来讲解CRT是如何来扩大模数的。
中国剩余定理(CRT)
系统来说就是,已知一个数x,m1,m2,m3 互素,x模m1余a,x模m2余b,x模m3余c,求x。
解法:M1= m2 * m3 ; M2 = m1 * m3 ; M3 = m1 * m2;
t1为M1的模m1逆元(t1*M1≡ 1 mod m1 )
t2为M2的模m2逆元
t3为M3的模m3逆元
则 x = a * M1 * t1 + b * M2 * t2 + c * M3 * t3 – m1 * m2 * m3 * k(适当选择k使得x为最小正值)
m
即:x = (a * M1 * t1 + b * M2 * t2 + c * M3 * t3)mod (m1 * m2 * m3) (此时是唯一解)
那么对于RSA:
a=cd mod p
b=cd mod q
有m=aqinv(q,p)+bpinv(p,q) mod n
正确性分析
再分析之前先回顾一下扩展欧几里得算法求二元一次方程组
1.给出正整数a,b;d=gcd(a,b) 求方程ax+by=d的一组整数解
gcd(a,b) =gcd(b,a mod b) ——①
a mod b = a - \(\lfloor a/b \rfloor\) b ——②
由①可知存在一组解(x',y')使得bx+(a mod b)y=d ——③
将②代入③并拆掉括号有bx'+ay'-\(\lfloor a/b \rfloor\)by=d
转化一下有ay'+b(x'-\(\lfloor a/b \rfloor\)y)=d
因此x=y' and y=(x'-\(\lfloor a/b \rfloor\)*y)
然后按照辗转相除法我们最后会得到a'x+b'y=d 其中a=d,b=0
那么我们可以不断还原得到ax+by=d的特解
def gcd(m,n):
if n == 0: #若n 能等于零说明已经除尽 n 就是它的最大公约数
return n
else:
return gcd(n,m%n) #将n 变成m 将m/n作n 继续除,符合辗转相除法的步骤
def exgcd(a,b):
if b==0:
return 1,0,a
else:
x,y,gcd=exgcd(b,a%b) #递归到最初状态
x,y=y,x-(a//b)*y #根据最初状态去还原当前解
return x,y,gcd
2.等式两边同乘temp=c/gcd(a,b)则可以得到ax+by=c的形式(若c不整除gcd(a,b)则无整数解)
axtemp+bytemp=c
X=xtemp;Y=ytemp
即aX+bY=c
上述式子由于a,b是正整数,因此两个未知数的关系可以理解为此消彼长
显然满足a(X+nb)+b(Y-na)=c
因此通解为x=X+nb;y=Y-na
观察上面通解,可以发现a,b不一定就是最小伸缩量,由于a,b存在最大公约数,导致增长大了些,会跳过一些解。
因此我们将a,b除以gcd(a,b)即可
通解为X+nb/gcd(a,b);Y-na/gcd(a,b)
下面进入正题
这里只讨论Rsa情况,其余情况可以照着推
先讲解一下通解即p与q不互质
令x=cd
展开有x=a+k1p x=b+k2q ——①
做差得 pk1 - q k2 = a-b
通过刚才通解我们可以知道K1=k1+qt/gcd(p,q) K2=k2+pt/gcd(p,q)
将上面式子代入①任意一个可得 x=K1p+a = k1p+nt/gcd(p,q)+a
这里记k1n1+a1为x0得
x=x0+tlcm(p,q)
即x=x0 mod n
下面讲解p与q互质
ci=Miinv(Mi,ni)
我们知道方程的唯一解是 \(\sum_{i=0}^{k}(ai*ci)\)
对于i≠j有
ajcj=ajmjinv(mj,nj)
其中mj=n/nj 因此ajcj = 0 mod ni
i=j时有 aici=aimiinv(mi,ni)=ai mod ni
因此x=\(\sum_{j=0}^{k}(aj*cj)\)=\(\sum_{j=0,j≠i}^{k}(aj*cj)\)=aimod ni
def crt(remainders, moduli):
"""
中国剩余定理(CRT)求解同余方程组
remainders: 模数对应的余数列表,例如[2, 3, 2]表示x ≡ 2 (mod 3), x ≡ 2 (mod 5), x ≡ 2 (mod 7)
moduli: 模数列表,例如[3, 5, 7]
返回同余方程组的解,如果不存在解,则返回None
"""
from math import gcd
# 检查输入的参数是否合法
if len(remainders) != len(moduli):
return None
# 检查模数是否两两互质
for i in range(len(moduli)):
for j in range(i + 1, len(moduli)):
if gcd(moduli[i], moduli[j]) != 1:
return None
# 计算模数的乘积
M = 1
for m in moduli:
M *= m
# 计算Mi和ti
Mi = [M // m for m in moduli]
ti = [pow(Mi[i], -1, moduli[i]) for i in range(len(moduli))]
# 计算解x
x = sum([remainders[i] * Mi[i] * ti[i] for i in range(len(moduli))])
return x % M
Question
from Crypto.Util.number import *
flag=b'flag{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}'
m=bytes_to_long(flag)
p=getPrime(512)
q=getPrime(512)
assert p<m and q<m
n=p*q
e=65537
d=inverse(65537,(p-1)*(q-1))
c=pow(m,e,n)
c1=pow(c,d,p)
c2=pow(c,d,q)
EXP
print(long_to_bytes(c1))
print(long_to_bytes(c2))
c=crt([c1,c2],[p,q])
print(long_to_bytes(m))
b'_\xd1\xd3\xca\x08f{\x81R{.\x10\xd8\x11\xebo\xbb\x88\x82\xec|\xd2\x95/2g\xf9\x1a_\xbaI\x92\xbf(b\xcb\xd7\x84\x02\x81(\xb3}{\x16\x03\xcb\xa4]\xa9\xf5/\xdc\xb2E\xc7\xbb\xc4\x04\xf0W\x18\xe4='
b'\x89\xd7=\xfeI\x80"R\xa1\xb7\xc7f>\\\xd5\xb9\xe1\xe2\xd2\x8d\xe9\x88\xcb\xd1\x8a\'\xd5\x89\xb3\x9d\x95\xdb\xda\x90\x15\xfb\x14\x82L\xd13\xbc\x95\x04wY\x07\xc2H\x91\x95\xc1?A6\x88.J\x081\x97X|\xd8'
b'flag{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}'