ElGamal公钥密码算法(Python实现)

说明
这是某电网信院的密码学实验4

一、实验目的(包括实验环境、实现目标等等)

1、实验环境

  • Windows11
  • PyCharm2019.3.3 x64

2、实现目标

  • 通过编写代码实现EIGamal公钥密码算法,加深对EIGamal算法的理解,体会该算法在解决实际问题的价值;
  • 将密码学和数学知识相联系,并灵活运用到密码学的设计方案中;
  • 提高实践能力和逻辑思维能力

二、方案设计(包括背景、原理、必要的公式、图表、算法步骤等等)

1、背景

在密码学中,ElGamal加密算法是一个基于迪菲-赫尔曼密钥交换的非对称加密算法,它在1985年由塔希尔·盖莫尔提出。塔希尔·盖莫尔1955年出生于埃及开罗,密码学家。他是SSL的最初设计者,被称为SSL之父。EIGamal公开密钥密码体制是基于有限域中离散对数问题的难解性。它所根据的原理是:求解离散对数是困难的,而其逆运算可以应用平方乘的方法有效地计算出来。在相应的群 G中,指数函数是单向函数。所谓单向函数,它的意义就是在有限的算力之下如果你希望逆向去求的话是不可能做到的。

2、离散对数困难问题

设g是模p的一个原根,任一整数h,
(1)给定整数x,计算元素g ^ x ≡ h (mod ⁡p )很容易
(2)给定整数h,计算整数x,0 ≤ x ≤ P - 2,使得g ^ x ≡ h (mod ⁡p )非常困难

3、EIGamal公钥加密算法

密钥产生过程
(1)随机产生一个大素数p及模p的一个原根g;
(2)随机选取整数a,计算g ^ x (mod⁡ p)。
Alice的公钥是(p, g, g ^ a),私钥是a。
加密过程
Bob将明文消息m加密成密文
(1)随机选取一个整数k,1≤ k ≤ P - 2;
(2)计算C1≡g ^ x (mod ⁡p ),C2 ≡ m (g ^ a ) ^ k (mod⁡ p );
(3)将密文(C1,C2)发送给Alice。
解密过程
Alice将密文(C1,C2)恢复为明文m
ElGamal公钥密码算法(Python实现)_第1张图片

4、实验准备

(1)强素数:在这里,定义强素数为:若p为一个素数,且q=2p+1也是一个素数,则称q是一个强素数。
(2)欧拉函数:在数论中,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目。此函数以其首名研究者欧拉命名,它又称为∅函数(由高斯命名)。
(3)原根:原根是一种数学符号,设m是正整数,a是整数,若a模m的阶等于∅(m),则称a为模m的一个原根。(其中∅(m)表示m的欧拉函数,即a^(∅(m) )≡1(mod ⁡m ))

三、方案实现(包括算法流程图、主要函数的介绍、算法实现的主要代码等等)

1、流程图

ElGamal公钥密码算法(Python实现)_第2张图片

2、主要函数

(1)sys.setrecursionlimit(10000):递归深度设置为10000,防止递归深度不够
(2)def fastExpMod():快速取模幂
(3)def primitive_element():生成原根
(4)def e_gcd()
(5)def encrypt():Bob加密
(6)def decrypt():Alice解密

3、Python代码

from random import randint
import sympy
import sys

sys.setrecursionlimit(10000)


def fastExpMod(a, e, m):
    a = a % m
    res = 1
    while e != 0:
        if e & 1:
            res = (res * a) % m
        e >>= 1
        a = (a * a) % m
    return res


def primitive_element(p, q):
    while True:
        g = randint(2, p - 2)
        if fastExpMod(g, 2, p) != 1 and fastExpMod(g, q, p) != 1:
            return g


def e_gcd(a, b):
    if b == 0:
        return a, 1, 0
    g, x, y = e_gcd(b, a % b)
    return g, y, x - a // b * y


def encrypt(p, g, y, m):
    while True:
        k = randint(2, p - 2)
        if e_gcd(k, p - 1)[0]:
            break
    c1 = fastExpMod(g, k, p)
    c2 = (m * fastExpMod(y, k, p)) % p
    return c1, c2


def decrypt(c1, c2, p, a):
    v = fastExpMod(c1, a, p)
    v_1 = e_gcd(v, p)[1]
    m_d = c2 * v_1 % p
    return m_d


def main():
	# 这里的路径:读者自己电脑测试文件存放的正确路径
    m = int(open("F:\密码学实验\secret2.txt").readline())
    while True:
        q = sympy.randprime(10 ** 149, 10 ** 150 / 2 - 1)
        if sympy.isprime(q):
            p = 2 * q + 1
            if len(str(p)) == 150 and sympy.isprime(p):
                break
    g = primitive_element(p, q)
    a = randint(2, p - 2)
    y = fastExpMod(g, a, p)
    c1, c2 = encrypt(p, g, y, m)
    m_d = decrypt(c1, c2, p, a)

    if m == m_d:
        print("解密结果与明文相同!解密正确!")
    else:
        print("解密结果与明文不同!解密不正确!")
    return m, p, g, y, c1, c2, m_d


if __name__ == '__main__':
    print("m = %d\nALice的公钥:\np = %d\ng = %d\ng^a = %d\n密文(C1, C2) = (%d,\n%d)\n明文m = %d"
          % main())

四、数据分析(包括算法测试数据的分析,运行结果截图等等)

1、secret0

9327260388393076415930260479153046010064951650867096323260782111903507989221223155043829435161867334962529353992935468294479465522637777146290777

运行结果:
ElGamal公钥密码算法(Python实现)_第3张图片

2、secret1

268934047525129207430358090155831774406988263017537886266459743124401877032780923870438637078936998897356703572131607069480172048042746

运行结果:
ElGamal公钥密码算法(Python实现)_第4张图片

3、secret2

53440167287330489793805749223384077746504290188205908391653679301485458082326877556058376895190593105090632340942230488922602

运行结果:
ElGamal公钥密码算法(Python实现)_第5张图片

五、思考与总结

1、请简述什么是本原根,给定素数P,如何求其本原根?

  • 本原根:原根是一种数学符号,设m是正整数,a是整数,若a模m的阶等于∅(m),则称a为模m的一个原根。(其中∅(m)表示m的欧拉函数,即a^(∅(m) )≡1(mod m ))。
  • 生成本原根的方法有很多,比如遍历、判断等;本实验选取的方法为:随机生成一个素数p,若p为一个素数,且q = 2p + 1也是一个素数,则称q是一个强素数。接着随机生成一个整数g (1 < g < P - 1),若g ^ 2 ≠ 1,且g ^ q ≠ 1,则g是大素数p的一个本原根。

你可能感兴趣的:(密码学实验,算法)