跳转至

P13. dp,dq

P13.dp,dq

出题脚本

#coding:utf-8
import random
import base64
import hashlib
import string
import libnum

def put_flag():
    # 字符串列表
    a = string.printable
    flag = ""
    for i in range(10):
        flag += a[random.randint(0, 99)]
    flag = r"flag{%s}"%(hashlib.md5(flag.encode()).hexdigest())
    print(flag)
    return flag
#生成素数
p=libnum.generate_prime(1024)
q=libnum.generate_prime(1024)
e=65537
n=p*q
phi_n=(p-1)*(q-1)
d=libnum.invmod(e,phi_n)
dp=d%(p-1)
dq=d%(q-1)
m=put_flag()
m=libnum.s2n(m)
n=p*q
c=pow(m,e,n)

print("p=",p)
print("q=",q)
print("dq=",dq)
print("dp=",dp)
print("c=",c)

解题脚本

# coding=utf-8
import gmpy2
import libnum

def decrypt(dp,dq,p,q,c):
    InvQ = gmpy2.invert(q, p)
    mp = pow(c, dp, p)
    mq = pow(c, dq, q)
    m = (((mp-mq)*InvQ) % p)*q+mq
    print(libnum.n2s(int(m)).decode())

p= 
q= 
dq= 
dp= 
c= 

decrypt(dp,dq,p,q,c)

题目解析

c = m^e mod n

m = c^d mod n

ϕ(n)= (p−1)∗(q−1)

d∗e≡ 1 mod ϕ(n)

dp= d mod (p−1)

dq= d mod (q−1)
首先根据

m=c^d mod n

gcd(p,q)=1
n=p∗q

利用中国剩余定理,得:
m1=c^d mod p
m2=c^d mod q
m=c^d mod n
m=c^d+k∗n

n=p∗q
m=c^d+p∗q∗k


同时取余q和p

m1≡c^d mod q
m2≡c^d mod p

c^d=kp+m1


式1带入式2
m2≡(kp+m1) mod q

等式两边同时减去m1,
(m2−m1)≡kp mod q

gcd(p,q)=1

所以可以求p的逆元,得到
(m2−m1)∗p1≡k mod q

得到如下两个式子
k≡(m2−m1)∗p1mod q
c^d=kp+m1
m≡c^d mod n


上下两个式子合并

c^d = ((m2−m1)∗p1 mod q)p+m1
m ≡ c^d mod n

最后可以有

m≡(((m2−m1)∗p1 mod q)p+m1) mod n

只剩最后一步了

m1≡cd mod q
m2≡cd mod p

m1和m2怎么求

d≡dp mod (p−1)
d≡dq mod (q−1)

那么分别带入

m1≡cdq mod (q−1) mod q
m2≡cdp mod (p−1) mod p

费马小定理即假如p是质数,且gcd(a,p)=1
a(p−1)≡1 mod p

所以如果我们有等式

d=dp+k∗(p−1)

直接带入
m2≡c^dp+k∗(p−1) mod p

这里的指数,我们拆开,为
m2≡c^dp∗ck∗(p−1) mod p

ck∗(p−1)≡1 mod p

因为p是大素数,显然和c互素所以可以直接得到
m2≡cdp mod p

那么m1根据对称性也可以同理得到

m1≡cdq mod q

故此,我们现在拥有了所有条件,下面归纳一下为

m1≡cdq mod q
m2≡cdp mod p
m≡(((m2−m1)∗p1 mod q)p+m1) mod n