编程实现RSA数字签名

一、实验目的:

理解RSA数字签名,并运用编程实现RSA数字签名。

二、实验过程:

1.学习RSA算法及RSA数字签名算法流程。

2. RSA数字签名原理:当发送方想要给接收方发送数据,并想进行数字签名的时候,发送方只需要利用自己的私钥,对数据进行数字签名算法,就可以得到一个新的签名数据,这时发送方需要把自己原来的数据,以及新得到的签名数据都发送给接收方,接收方接受到签名数据之后,用发送方的公钥对签名数据进行验证算法,看得出来的数据与发送方发送过来的数据是不是完全一样的即可。

三、实验代码及结果:

(1)实验代码:

import random

import math

#快速幂取模

def power(a, b, n):  #计算a**b mod n

    if b == 0:

        return 1      #如果b值为0则返回1

    elif b % 2 == 0:  # 如果二进制b最后一位为0

        p = power(a, b / 2, n)      #递归实现

        return (p * p) % n    #取模运算

    else:

        return (a * power(a, b - 1, n)) % n       #返回结果

# 欧几里得算法求最大公约数

def gcd(a, b):

    if a < b:

        return gcd(b, a)        #如果a小于b,交换两个数

    elif a % b == 0:

        return b      #如果a整除于b则返回b

    else:

        return gcd(b, a % b)        #递归实现欧几里得算法

#确定是否是素数

def isPrime(num):

    if (num < 2):

        return False              #如果num的值小于2返回false

    else:

        i = 2

        flag=True

        while i < num:  # 如果num能被i整除,说明num不是质数

            if num % i == 0:

                flag = False     # 只要num不是质数,将flag的值修改为 False

            i += 1

        return  flag      #最后返回flag的值

#生成大素数函数

def randPrime(n):

    Start = 10 ** (n-1)   #n的值为5,计算开始值10**4

    End = (10 ** n) - 1  #计算结束10**5-1

    while True:

        num = random.randint(Start, End)  #返回从start到end之间任意一个数表示大素数

        if isPrime(num):      #判断是否是质数,如果是则生成

            return num       #返回大素数的值num

# 扩展的欧几里得算法,即ab=1 (mod n), 得到a在模n下的乘法逆元b

def Extended_Eulid(a, n):

    x1, x2, x3 = 1, 0, n

    y1, y2, y3 = 0, 1, a

    while y3 != 1 and y3 != 0 and y3 > 0:

        Q = math.floor(x3 / y3)

        t1, t2, t3 = x1 - Q * y1, x2 - Q * y2, x3 - Q * y3

        x1, x2, x3 = y1, y2, y3

        y1, y2, y3 = t1, t2, t3

    if y3 == 0:

        return 0

    if y3 == 1:

        if y2 >0:

            return y2

        else:

            return n+y2

# 生成公钥和私钥

def KeyGen(p, q):      #分别计算n,e,d的值

    n = p * q

    e = random.randint(1, (p - 1) * (q - 1))

    while gcd(e, (p - 1) * (q - 1)) != 1:       #运用欧几里得算法判断

        e = random.randint(1, (p - 1) * (q - 1))

    d = Extended_Eulid(e, (p - 1) * (q - 1))

    return n, e, d

#利用快速幂取模计算签名

def Sign(x, d, n):

    s = power(x, d, n)

    return s

#利用快速幂取模判断是否有效签名

def Verify(s, e, n):

    x_ = power(s, e, n)

    return x_

#主函数

if __name__ == '__main__':

    key_size = 5

    p = randPrime(key_size)        #p与q分别为随机生成的大素数

    q = randPrime(key_size)

    n, e, d = KeyGen(p, q)            #用p与q生成公钥和私钥

    # 输入消息

    x = int(input("请输入加密信息(必须为整数): "))

   

    # 计算签名

    s = Sign(x, d, n)

    # 验证签名

    x_ = Verify(s, e, n)

    Valid = (x_ == x)

    # 伪造数据攻击

    s_ = random.randint(1, (p - 1) * (q - 1))

    m_ = random.randint(1, (p - 1) * (q - 1))

    # 输出

    print("私钥: ")

    print("N: ", n)

    print("d: ", d)

    print("公钥: ")

    print("N: ", n)

    print("e: ", e)

    print("签名: ")

    print("s: ", s)

    print("验证m的签名: ")

    if Valid:

        print("签名有效")

    else:

        print("签名无效")

    print("m'(伪): ", m_)

    if Verify(m_, s, n) == x:

        print("签名有效")

    else:

        print("签名无效")

    print("s' (伪): ", s_)

    if Verify(x_, s_, n) == x:

        print("签名有效")

    else:

        print("签名无效")

import random

import math



#快速幂取模

def power(a, b, n):  #计算a**b mod n

    if b == 0:

        return 1      #如果b值为0则返回1

    elif b % 2 == 0:  # 如果二进制b最后一位为0

        p = power(a, b / 2, n)      #递归实现

        return (p * p) % n    #取模运算

    else:

        return (a * power(a, b - 1, n)) % n       #返回结果



# 欧几里得算法求最大公约数

def gcd(a, b):

    if a < b:

        return gcd(b, a)        #如果a小于b,交换两个数

    elif a % b == 0:

        return b      #如果a整除于b则返回b

    else:

        return gcd(b, a % b)        #递归实现欧几里得算法



#确定是否是素数

def isPrime(num):

    if (num < 2):

        return False              #如果num的值小于2返回false

    else:

        i = 2

        flag=True

        while i < num:  # 如果num能被i整除,说明num不是质数

            if num % i == 0:

                flag = False     # 只要num不是质数,将flag的值修改为 False

            i += 1

        return  flag      #最后返回flag的值



#生成大素数函数

def randPrime(n):

    Start = 10 ** (n-1)   #n的值为5,计算开始值10**4

    End = (10 ** n) - 1  #计算结束10**5-1

    while True:

        num = random.randint(Start, End)  #返回从start到end之间任意一个数表示大素数

        if isPrime(num):      #判断是否是质数,如果是则生成

            return num       #返回大素数的值num



# 扩展的欧几里得算法,即ab=1 (mod n), 得到a在模n下的乘法逆元b

def Extended_Eulid(a, n):

    x1, x2, x3 = 1, 0, n

    y1, y2, y3 = 0, 1, a

    while y3 != 1 and y3 != 0 and y3 > 0:

        Q = math.floor(x3 / y3)

        t1, t2, t3 = x1 - Q * y1, x2 - Q * y2, x3 - Q * y3

        x1, x2, x3 = y1, y2, y3

        y1, y2, y3 = t1, t2, t3

    if y3 == 0:

        return 0

    if y3 == 1:

        if y2 >0:

            return y2

        else:

            return n+y2

# 生成公钥和私钥

def KeyGen(p, q):      #分别计算n,e,d的值

    n = p * q

    e = random.randint(1, (p - 1) * (q - 1))

    while gcd(e, (p - 1) * (q - 1)) != 1:       #运用欧几里得算法判断

        e = random.randint(1, (p - 1) * (q - 1))

    d = Extended_Eulid(e, (p - 1) * (q - 1))

    return n, e, d

#利用快速幂取模计算签名

def Sign(x, d, n):

    s = power(x, d, n)

    return s

#利用快速幂取模判断是否有效签名

def Verify(s, e, n):

    x_ = power(s, e, n)

    return x_

#主函数

if __name__ == '__main__':

    key_size = 5

    p = randPrime(key_size)        #p与q分别为随机生成的大素数

    q = randPrime(key_size)

    n, e, d = KeyGen(p, q)            #用p与q生成公钥和私钥



    # 输入消息

    x = int(input("请输入加密信息(必须为整数): "))

   

    # 计算签名

    s = Sign(x, d, n)

    # 验证签名

    x_ = Verify(s, e, n)

    Valid = (x_ == x)



    # 伪造数据攻击

    s_ = random.randint(1, (p - 1) * (q - 1))

    m_ = random.randint(1, (p - 1) * (q - 1))



    # 输出

    print("私钥: ")

    print("N: ", n)

    print("d: ", d)

    print("公钥: ")

    print("N: ", n)

    print("e: ", e)

    print("签名: ")

    print("s: ", s)

    print("验证m的签名: ")

    if Valid:

        print("签名有效")

    else:

        print("签名无效")



    print("m'(伪): ", m_)

    if Verify(m_, s, n) == x:

        print("签名有效")

    else:

        print("签名无效")

    print("s' (伪): ", s_)

    if Verify(x_, s_, n) == x:

        print("签名有效")

    else:

        print("签名无效")

(2)实验结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值