【密码学】Python实现Elgamal数字签名算法

程序要求清单:
在这里插入图片描述

基本流程:
在这里插入图片描述

在这里插入图片描述

运行结果:

INPUT:
4137696876930090267522398697653550193405311689664069574322834683213199126531348263326633721504049779673544721298253021191958429503842792929508773630980912

OUTPUT:
Private Key:
p: 8060327021536227333871375435814162054749574145337465015262790431994321280024183625740467314529848040912931632347776012809455330153993666794346377060718839
alpha: 1284633945749092889233783148765297267529010377059231884764879337883527984047121889658429050477643695682495490232004786638385456145084193469036162689305604
a: 526674071621370396436413471872860117705285788442694498240440134454125899239205358772900705818792449874418340323345439148477313563215497453028350007435320
Public key :
p: 8060327021536227333871375435814162054749574145337465015262790431994321280024183625740467314529848040912931632347776012809455330153993666794346377060718839
alpha: 1284633945749092889233783148765297267529010377059231884764879337883527984047121889658429050477643695682495490232004786638385456145084193469036162689305604
beta: 4915525385307472715728788674664988536793158944213857163795095873590306114931600021441240617110385674165775456078547313829641256459616888887913104693601923
Signature:
r: 5952158039737258220633308519112993779188069228212694173370689308695228294675101254631052416028393803694294466261012253800110481456143514893593177601190278
s: 6311788141658007604521807380314404602094073406047499052980130566929851556243517107556077669907131256390358095811379134970299419421281417284875743462235508
Verify (r, s) of x:
valid
x’ (faked): 830079393891223851172041723063270619748451134683945806411105614438730576977296513855580068019966659759573361641996013385693709341802096801497071178643610737305
Verify (r, s) of x’:
invalid
r’ (faked): 3079373857591398633749935715889360575509432885323344077098906224895726981255581559126521407722116685111082979380844472504213683010074082433733766065453153326064
s’ (faked): 8606952315660680838439288799955577928960051556166481137602110894711116191210812894992525824129531774970695344835999618853408895546598240200116700927261394893041
Verify (r’, s’) of x:
invalid

代码实现:

import random


# 求最大公约数
def gcd(a, b):
    if a < b:
        return gcd(b, a)
    elif a % b == 0:
        return b
    else:
        return gcd(b, a % b)


# 快速幂+取模
def power(a, b, c):
    ans = 1
    while b != 0:
        if b & 1:
            ans = (ans * a) % c
        b >>= 1
        a = (a * a) % c
    return ans


# 大素数检测
def Miller_Rabin(n):
    a = random.randint(2,n-2) #随机第选取一个a∈[2,n-2]
    # print("随机选取的a=%lld\n"%a)
    s = 0 #s为d中的因子2的幂次数。
    d = n - 1
    while (d & 1) == 0: #将d中因子2全部提取出来。
        s += 1
        d >>= 1

    x = power(a, d, n)
    for i in range(s): #进行s次二次探测
        newX = power(x, 2, n)
        if newX == 1 and x != 1 and x != n - 1:
            return False #用二次定理的逆否命题,此时n确定为合数。
        x = newX

    if x != 1:  # 用费马小定理的逆否命题判断,此时x=a^(n-1) (mod n),那么n确定为合数。
        return False

    return True  # 用费马小定理的逆命题判断。能经受住考验至此的数,大概率为素数。


# 扩展的欧几里得算法,ab=1 (mod m), 得到a在模m下的乘法逆元b
def Extended_Eulid(a: int, m: int) -> int:
    def extended_eulid(a: int, m: int):
        if a == 0:  # 边界条件
            return 1, 0, m
        else:
            x, y, gcd = extended_eulid(m % a, a)  # 递归
            x, y = y, (x - (m // a) * y)  # 递推关系,左端为上层
            return x, y, gcd  # 返回第一层的计算结果。
        # 最终返回的y值即为b在模a下的乘法逆元
        # 若y为复数,则y+a为相应的正数逆元

    n = extended_eulid(a, m)
    if n[1] < 0:
        return n[1] + m
    else:
        return n[1]


# 生成域参数p,长度大约为512bits
def Generate_p() -> int:
    a = random.randint(10**150, 10**160)
    while gcd(a, 2) != 1:
        a = random.randint(10**150, 10**160)
    return a


# 生成域参数alpha
def Generate_alpha(p: int) -> int:
    return random.randint(2, p)


# 生成一个小于p的素数作为私钥,长度大约为512bits
def Generate_private_key(p: int) -> int:
    pri = random.randint(2, p - 2)
    while gcd(pri, p) != 1:
        pri = random.randint(2, p - 2)
    return pri


# 快速幂
def quick_power(a: int, b: int) -> int:
    ans = 1
    while b != 0:
        if b & 1:
            ans = ans * a
        b >>= 1
        a = a * a
    return ans


def Generate_prime(key_size: int) -> int:
    while True:
        num = random.randrange(quick_power(2, key_size - 1), quick_power(2, key_size))
        if Miller_Rabin(num):
            return num


# 计算签名
def Sign(x, p, alpha, d) -> []:
    temp_key = random.randint(0, p - 2)
    while gcd(temp_key, p - 1) != 1:
        temp_key = random.randint(0, p - 2)
    r = power(alpha, temp_key, p)
    s = (x - d * r) * Extended_Eulid(temp_key, p - 1) % (p - 1)
    return r, s


# 签名验证
def Verify(x, p, alpha, beta, r, s):
    t = (power(beta, r, p) * power(r, s, p)) % p
    if t == power(alpha, x, p):
        return True
    else:
        return False


if __name__ == '__main__':
    x = int(input("Message:       "))
    if type(x) != int:
        raise ValueError("Must be an integer!")

    p = Generate_prime(512)
    alpha = Generate_alpha(p)
    a = Generate_private_key(p)
    beta = power(alpha, a, p)

    r, s = Sign(x, p, alpha, a)
    Valid = Verify(x, p, alpha, beta, r, s)

    r_ = random.randint(10 ** 150, 10 ** 160)
    s_ = random.randint(10 ** 150, 10 ** 160)
    x_ = random.randint(10 ** 150, 10 ** 160)

    print("Private Key: ")
    print("p:            ", p)
    print("alpha:        ", alpha)
    print("a:            ", a)
    print("Public key : ")
    print("p:            ", p)
    print("alpha:        ", alpha)
    print("beta:         ", beta)
    print("Signature: ")
    print("r:            ", r)
    print("s:            ", s)
    print("Verify (r, s) of x: ")
    if Verify(x, p, alpha, beta, r, s):
        print("valid")
    else:
        print("invalid")
    print("x' (faked): ", x_)
    print("Verify (r, s) of x': ")
    if Verify(x_, p, alpha, beta, r_, s_):
        print("valid")
    else:
        print("invalid")

    print("r' (faked): ", r_)
    print("s' (faked): ", s_)
    print("Verify (r', s') of x: ")
    if Verify(x, p, alpha, beta, r_, s_):
        print("valid")
    else:
        print("invalid")
  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值