Rabin公钥密码系统

Rabin公钥密码系统

实现描述

  1. 密钥产生:随机生成两个大的素数,p和q,满足 p ≡ q ≡ 3 m o d 4 p\equiv q\equiv 3 \quad mod \quad4 pq3mod4 ,计算 n=pq, n 为公钥,p,q作为私钥。
  2. 加密: c = m 2 m o d n c = m^2 \quad mod \quad n c=m2modn
  3. 解密:就是求c模n的平方根,即解 x 2 ≡ c m o d n x^2\equiv c \quad mod \quad n x2cmodn,该方程等价于方程组
    { x 2 ≡ c m o d p x 2 ≡ c m o d q \left\{ \begin{aligned} x^2 \equiv c \quad mod \quad p\\ x^2 \equiv c \quad mod \quad q \end{aligned} \right. {x2cmodpx2cmodq
    在这里插入图片描述

由于 p ≡ q ≡ 3 m o d 4 p \equiv q \equiv 3 \quad mod \quad 4 pq3mod4,可以容易地求出c在模p下的两个方程根,即

x ≡ c p + 1 4 m o d p x \equiv c^{\frac {p+1}{4}\quad }mod \quad p xc4p+1modp; x ≡ p − c p + 1 4 m o d p x \equiv p - c^{\frac {p+1}{4}\quad }mod \quad p xpc4p+1modp

和c在模q下的两个方程根,即

x ≡ c q + 1 4 m o d q x \equiv c^{\frac {q+1}{4}\quad }mod \quad q xc4q+1modq; x ≡ q − c q + 1 4 m o d q x \equiv q-c^{\frac {q+1}{4}\quad }mod \quad q xqc4q+1modq

两两组合即可得到四个方程组,即可解出4个解,其中一个解为明文。

解密算法

输入:密文c,私钥p,q(p,q均为4k+3的素数,n=pq)

输出:明文

RabinDecrypt(c,p,q){

  1. 利用拓展欧几里得算法求出,s,t,使得,sp+tq = 1
  2. 计算 u ← c p + 1 4 m o d p u \gets c^{\frac {p+1}{4}} mod \quad p uc4p+1modp
  3. 计算 v ← c q + 1 4 m o d q v \gets c^{\frac {q+1}{4}} mod \quad q vc4q+1modq
  4. 计算 m 1 ← ( u t q + v s p ) m o d n m_1 \gets (utq+vsp) mod \quad n m1(utq+vsp)modn
  5. 计算 m 2 ← ( u t q − v s p ) m o d n m_2 \gets (utq-vsp) mod \quad n m2(utqvsp)modn
  6. 结果为,m1,n-m1,m2,n-m2,其中一个给明文

}

算法实现

import random
import time

# 判断是否为素数
# rabin_miller 法判定是否为素数
def rabin_miller(num):
    s = num - 1
    t = 0
    while s % 2 == 0:
        s = s // 2
        t += 1

    for trials in range(5):
        a = random.randrange(2, num - 1)
        v = pow(a, s, num)
        if v != 1:
            i = 0
            while v != (num - 1):
                if i == t - 1:
                    return False
                else:
                    i = i + 1
                    v = (v ** 2) % num
    return True


# 判断是否为素数
# 判断可能失效,因为该方法有伪素数存在
def is_prime(n):
    if n == 0:
        return False
    return 1 == square_and_multiply(17, n - 1, n)


# 莫重复平方运算 b^n%m
def square_and_multiply(b, n, m):
    bi = b
    ai = 1
    k = len("{0:b}".format(n))
    for i in range(0, k):
        if (n >> i & 1) == 1:
            ai = ai * bi % m
        bi = bi ** 2 % m
    return ai


# 拓展欧几里得 , 求逆
def ex_gcd(a, b):
    if b == 0:
        return 1, 0, a
    else:
        s, t, r = ex_gcd(b, a % b)
        s, t = t, (s - (a // b) * t)
        return s, t, r


# 密钥生成
# return p,q,n, (p,q) is private key, n is public key
def key_generator():
    p = 0
    q = 0
    n = 0
    while (p - 3) % 4 != 0 or (q - 3) % 4 != 0 or p == q:
        random.seed(time.time())
        # 可以取非常大的值
        p = random.randint(2 ** 300, 2 ** 400)
        q = random.randint(2 ** 300, 2 ** 400)
    while not is_prime(p) or not is_prime(q):
        p += 4
        q += 4
    n = p * q
    return p, q, n


# 加密
# m is plaintext, n is public key
# 该算法通过重复明文方法来区分四个解
def encode(m, n):
    m1 = str(m)
    m1 = int(m1 + m1)
    c = m1 ** 2 % n
    return c


# 处理4个解的子方法
def sub_handle_decode_res(m):
    if len(m) % 2 != 0:
        return False
    i = 0
    while i < len(m) // 2:
        if m[i] != m[len(m) // 2 + i]:
            return False
        i = i + 1
    return m[:len(m) // 2]


# 处理4个解的情况
def handle_decode_res(m1, m2, m3, m4):
    m1_str = sub_handle_decode_res(str(m1))
    m2_str = sub_handle_decode_res(str(m2))
    m3_str = sub_handle_decode_res(str(m3))
    m4_str = sub_handle_decode_res(str(m4))
    if m1_str:
        return m1_str
    if m2_str:
        return m2_str
    if m3_str:
        return m3_str
    if m4_str:
        return m4_str


# 解密
def decode(c, p, q, n):
    s, t, r = ex_gcd(p, q)
    u = square_and_multiply(c, (p + 1) // 4, p)
    v = square_and_multiply(c, (q + 1) // 4, q)
    m1 = int(u * t * q + v * s * p) % n
    m2 = int(u * t * q - v * s * p) % n
    return handle_decode_res(m1, n - m1, m2, n - m2)


if __name__ == '__main__':
    p, q, n = key_generator()
    # 处理公钥私钥。
    print("p is {},q is {}, n is {}".format(p, q, n))
    m = input("请输入明文:")
    c = encode(int(m), n)
    print("密文为 {}".format(c))
    m = decode(c, p, q, n)
    print("明文为 {}".format(m))

思考

  1. 该密钥系统相当于单工通信,需要两对密钥才能实现双方通信
  2. 对于明文流应该进行处理,使其平方后应该大于m,
  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IPrivacy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值