【公钥密码】ECC椭圆密码体制 (实现Elgamal加密方法)

CryptoAlgor 项目地址 (四个实验完整源码)

        1. Github 项目地址
        2. Gitee 项目地址

        该项目的目录:

        1.四个古典密码       /classcipher

        2.DES分组密码        /descipher

        3.RSA公钥密码        /rsacipher

        4.ECC公钥体制(Elgamal加密)    /ellipticc

至此,四个加密实验完毕,均以Python实现。

四种加密都已经封装成Pyhon模块,直接调用即可。

目录

CryptoAlgor 项目地址 (四个实验完整源码)

1.关于 ECC 的依赖算法

 2. ECC椭圆曲线类

 3.基于 ECC 实现 Elgamal 加密方法


1.关于 ECC 的依赖算法

        1. 判断是否有平方剩余,并求解平方剩余的根

        2.求分式模p的正整数同余式

# 本文件名为 __util.py
from fractions import Fraction

def gcd(x, y):
	""" 欧几里德算法 """
	while x > 0:
		x, y = y % x, x
	return y


def extendGcd(a, b):
    """ 扩展欧几里德算法 求同余式
        求 a*x +b*y = gcd(a,b) 解
    """
    if b == 0:
        return a, b
    else:
        x, y = extendGcd(b, a % b)
        x, y = y, x - (a//b) * y
        return x, y


def isQuadricReside(a, p):
    """ 判断 a 是否为 素数p 的`平方剩余`
        ---------------------------
        * return 0 : a 被 p 整除
        * return 1 : a 是模 p 的平方剩余
        * return-1 : a 不是模 p 的平方剩余
    """
    legendre = (a**int((p - 1) / 2)) % p
    if legendre > 1: legendre -= p

    return legendre


def calcResideRoot(a, p):
    """ 求模 p 的平方剩余 a 的两个平方根
        ---------------------------
        即方程 x^2 = a mod p 的解 
        * retrun : 元组解(x1, x2)⛄
    """
    for i in range(1, p):
        if (i**2) % p == a:
            return (i, p - i)


def calcCongruence(n, p):
    """ 计算 a mod p 的同余正整数
        ----------------------
        * n : 分数、负数等
        * p : 素数
        * retrun : 同余的正整数
    """
    if isinstance(n, int):
        # 若a为整数, 则直接得到正整数同余式
        return n % p

    # 若n为分数b/a, 则计算得到正整数同余式
    # 即求不定 a*x + p*y = b 的解 x
    a, b = n.denominator, n.numerator
    coef = b  // gcd(a, p)
    x, _ = extendGcd(a, p)
    return (coef * x) % p


 2. ECC椭圆曲线类

         1.创建 ECC 类,实现生成 交换群 Ep(a,b),

        2.并实现群的基本算术运算。

# 本文件名为: ecc.py
from fractions import Fraction
from __util import *

class ECC():
    """ 椭圆曲线密码体制
        实现椭圆曲线点的运算, 消息的加密等
        可应用于 Elgamal 加密
        ------------------------------
        此 ECC类 用到运算符重载, 代码较复杂
        可以参看简化版:`ecc2.py`中的 ECC类
        曲线方程: y^2 = x^3 + ax - b
        * a : Ep(a, b) 中的 a
        * b : Ep(a, b) 中的 b
        * p : GF(p), y^2 mod p 中的 p
    """
    def __init__(self, a, b, p):
        if 4 * a**3 + 27 * b**2 == 0:
            print("非法椭圆曲线,请重新输入")
        self.__class__.a = a # __class__表示设为类成员属性 
        self.__class__.b = b # 以便内部类point访问
        self.__class__.p = p

    def genEset(self):
        """ 生成椭圆曲线的坐标点集 Ep(a, b) 
            * return : 坐标点集 [(x1,y1), (x2,y2), ··· ]
        """
        a, b, p = self.a, self.b, self.p

        Eset = [EO.point] # 定义一个`点集Ep(a,b)`的加法幺元
        for x in range(0, p):
            sqr = (x**3 + a*x + b) % p  # 计算待开方的值
            if isQuadricReside(sqr, p) == 1:
                # 若 sqr 是 p 的平方剩余, 则求 sqr 的根
                solution = calcResideRoot(sqr, p)
                Eset.append((x, solution[0]))
                Eset.append((x, solution[1]))
        return  Eset

    class point():
        """ Ep(a,b)中`坐标点(x, y)`实例化为`point对象`
            --------------------------------------
            实例化后的point对象可做 + - * 等运算
        """
        def __init__(self, *point):
            """ 获取实例对象ECC()中的 a, p, `坐标点point`
                * a, p : Ep(a, b) 中的 a, p
                * point : 椭圆曲线上的坐标点(x, y)
            """             
            # 继承外部类成员属性 ECC.a, ECC.p
            self.a, self.p, self.point = ECC.a, ECC.p, point

        def __add__(self, other):
            """ 重载运算符`+`: 定义椭圆上点的加法
                * self  : point对象 P:(x1, y1)
                * other : point对象 Q:(x2, y2)
                * retrun: point对象 P+Q:(x3,y3)
            """
            a, p, P, Q = self.a, self.p, self, other
            (x1, y1), (x2, y2) = self.point, other.point

            if P.point == EO.point: return Q   # EO+Q=Q
            if Q.point == EO.point: return P   # P+EO=P
            if x1==x2  and  y1!=y2: return EO  # P+Q=EO

            if x1!=x2: lamb = Fraction(y2-y1, x2-x1)
            if x1==x2: lamb = Fraction(3*x1*x1+a, 2*y1)
            lamb = calcCongruence(lamb, p)

            x3 = lamb**2 - x1 - x2
            x3 = calcCongruence(x3, p)
            y3 = lamb * (x1 - x3) - y1
            y3 = calcCongruence(y3, p)

            return ECC.point(x3, y3)

        def __mul__(self, coef):
            """ 重载运算符`*`: 椭圆上点的数乘 例如Point*3 """
            sums = self
            for _ in range(1, coef): sums += self
            return sums
        
        def __rmul__(self, other):
            """ 重载运算符`*`: 椭圆上点的数乘 例如3*Point """
            return self * other

        def __neg__(self):
            """ 重载运算符`-`: 椭圆上点的加法逆元 """
            x, y = (self.point[0], ECC.p-self.point[1])
            y = 0 if y == ECC.p else y
            return ECC.point(x, y)

        def __sub__(self, other):
            """ 重载运算符`-`: 椭圆上点的减法 """
            other = - other  # 返回加法逆元 则 P-Q = P+(-Q)
            return self + other

        def __repr__(self):
            """ 重载函数`print`: 打印对象point的点(x,y) """
            # 获取point对象的坐标点point (0,0)打印字母O
            disp = self.point 
            disp = 'O' if disp==EO.point else disp
            return str(disp)


# 全局变量: 自定义加法幺元, 即 EO.point = (0, 0)
# ECC()中数字随便, point(x,0)中 x随便, y必须是 0 或 p
EO = ECC(1,1,1).point('O', 'O')

""" 幺元为什么取('O', 'O') ?
    因为('O', 'O')连坐标都不是, 自然不在曲线 y^3=x^3+ax+b上
    它只是一个符号, 写成('O', 'O')只是因为坐标(x,y)有两个分量
    仅仅是为了方便运算, 它只是一个符号
"""

if __name__ == '__main__':

    ellip = ECC(1, 1, 23)   # 实例化一个 Ep(a,b) 对象
    P = ellip.point(3, 10)  # 实例化Ep(a,b)上的point对象
    Q = ellip.point(9, 7)   # 实例化Ep(a,b)上的point对象

    print("P+Q:",  P + P)

 3.基于 ECC 实现 Elgamal 加密方法

        1.以《现代密码学 杨波》例题4-36,验证 Elgaml 加密过程,

        2.并且基于 密文、明文 破解 Alice 的私钥。

# 本代码基于 ECC类 实现 Elgamal 加密
from ellipticc import ECC
import time


def takeTime(func):
    """ 装饰器: 计算函数运行耗时"""
    def decorated(*args):
        startime = time.time()
        func(*args)
        endtime  = time.time()
        taketime = round((endtime - startime)*10**3)
        print(f"->运算耗时: {taketime} 毫秒")
        return func
    return decorated


@takeTime
def Elgamal_exam436():
    # 利用ECC椭圆密码, 实现 Elgamma 加密
    # 公开椭圆曲线 ECC 的参数 Ep(a,b)、G
    # Alice 选择一整数私钥 Nk4
    # Alice 公开自己的公钥 PA=NA*G
    ellip = ECC(-1, 188, 751)
    G  = ellip.point(0, 376)
    PA = ellip.point(201, 5)

    # Bob 选择随机数 k, 对消息 PM 进行加密得到密文
    # Bob 发送密文 C = [(676, 558), (385, 328)]
    k  = 386
    PM = ellip.point(562, 201)
    C  = [k*G, PM + k*PA]

    print("\n密文为:", C)


@takeTime
def crackElgamal():
    """ 破解例题中 Alice 的私钥 """
    ellip = ECC(-1, 188, 751)
    PM = ellip.point(562, 201)
    C1 = ellip.point(676, 558)
    C2 = ellip.point(385, 328)

    for i in range(1, 1000):
        tmp = C2 - i*C1
        if tmp.point == PM.point:
            print("\nAlice选择的密钥为:", i)
            return i
    print("\n未破解成功, 请加大迭代次数")
    return 0


if __name__ == '__main__':

    Elgamal_exam436()
    crackElgamal()

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值