zoukankan      html  css  js  c++  java
  • 椭圆曲线在Fp域上的加密(python实现)

    椭圆曲线加密(python实现)

    在这里插入图片描述

    • 自己实现了一下,直接上代码

    # -*- coding: utf-8 -*-
    """
    ECC在Fp域上的加解密
    """
    
    
    def get_inverse_element(value, max_value):
        """
        计算value在1-max_value之间的逆元
        """
        for i in range(1, max_value):
            if (i * value) % max_value == 1:
                return i
        return -1
    
    
    def gcd_x_y(x, y):
        """
        计算最大公约数
        """
        if y == 0:
            return x
        else:
            return gcd_x_y(y, x % y)
        
    
    def calculate_p_q(x1,y1,x2,y2, a, p):
        """
        计算p+q
        """
        flag = 1  # 定义符号位
        if x1 == x2 and y1 == y2:
            member = 3 * (x1 ** 2) + a  # 计算分子
            denominator = 2 * y1    # 计算分母
        else:
            member = y2 - y1
            denominator = x2 - x1 
            if member* denominator < 0:
                flag = 0
                member = abs(member)
                denominator = abs(denominator)
        
        # 将分子和分母化为最简
        gcd_value = gcd_x_y(member, denominator)
        member = int(member / gcd_value)
        denominator = int(denominator / gcd_value)
        # 求分母的逆元    
        inverse_value = get_inverse_element(denominator, p)
        k = (member * inverse_value)
        if flag == 0:
            k = -k
        k = k % p
        # 计算x3,y3
        x3 = (k ** 2 - x1 - x2) % p
        y3 = (k * (x1 - x3) - y1) % p
        # print("%d<=====>%d" % (x3, y3))
        return [x3,y3]
        
    
    def get_order(x0, y0, a, b, p):
        """
        计算椭圆曲线的阶
        """
        # 计算-p
        x1 = x0
        y1 = (-1 * y0) % p
        temp_x = x0
        temp_y = y0
        n = 1
        while True:
            n += 1
            p_value = calculate_p_q(temp_x,temp_y, x0, y0, a, p)
            if p_value[0] == x1 and p_value[1] == y1:
                print("==========该椭圆曲线的阶为%d=========" % (n+1))
                return n+1
                
            temp_x = p_value[0]
            temp_y = p_value[1]
    
        # print("%d-%d-%d-%d" % (x0,y0,x1,y1))
    
    
    def get_x0_y0_x1_y1(x0, a, b, p):
        """
        计算p和-p
        """
        y0 = -1
        for i in range(0,p):
            if i ** 2 % p == (x0**3 + a*x0 + b) % p:
                y0 = i
                break
        
        # 如果y0找不到则返回False
        if y0 == -1:
            return False
        # 计算-y
        x1 = x0
        y1 = -1 * y0 % p
        # print("%d-%d-%d-%d" % (x0,y0,x1,y1))
        return [x0,y0,x1,y1]
    
    
    def draw_graph(a,b,p):
        """
        输出散列图
        """
        x_y = []
        for i in range(p):
            x_y.append(["-" for i in range(p)])
        
        for i in range(p):
            value = get_x0_y0_x1_y1(i, a, b, p)
            if value != False:
                x0 = value[0]
                y0 = value[1]
                x1 = value[2]
                y1 = value[3]
                # print("%d-%d-%d-%d" % (x0,y0,x1,y1))
                x_y[x0][y0] = 1
                x_y[x1][y1] = 1
        print("椭圆曲线的散列图为:")
        for j in range(p):
            if p-1-j >= 10:
                print(p-1-j, end=" ")
            else:
                 print(p-1-j, end="  ")
            for i in range(p):
                print(x_y[i][p-j-1], end="  ")
            print()
        print("   ",end="")
        for i in range(p):
            if i >= 10:
                print(i, end=" ")
            else:
                print(i, end="  ")
            
        print()
    
    
    def calculate_np(G_x, G_y, private_key, a, p):
        """
        计算nG
        """
        temp_x = G_x
        temp_y = G_y
        while private_key != 1:
            p_value = calculate_p_q(temp_x,temp_y, G_x, G_y, a, p)
            temp_x = p_value[0]
            temp_y = p_value[1]
            private_key -= 1
        return p_value
        
        
    def ecc_encrypt_and_decrypt():
        while True:
            a = int(input("请输入椭圆曲线的参数a:"))
            b = int(input("请输入椭圆曲线的参数b:"))
            p = int(input("请输入椭圆曲线的参数p(p为质数):"))
            
            if (4*(a**3) + 27*(b**2)) % p ==0:
                print("选取的椭圆曲线不能用于加密,请重新选择
    ")
            else:
                break
        # 输出该椭圆曲线的散点图
        draw_graph(a,b,p)
        print("在上图中选出一个点作为生成元G")
        G_x = int(input("你选取的横坐标G_x:"))
        G_y = int(input("你选取的纵坐标G_y:"))
        # 获取该椭圆曲线的阶
        n = get_order(G_x, G_y, a, b, p)
        # 获取私钥并且key < 椭圆曲线的阶n
        private_key = int(input("输入私钥key(<%d):" % n))
        # 计算公钥 nG
        Q = calculate_np(G_x,G_y,private_key,a,p)
        print("==================生成公钥{a=%d,b=%d,p=%d,阶%d,G(%d,%d),Q(%d,%d)}======" % (a, b, p, n, G_x, G_y , Q[0], Q[1]))
        
        # 加密开始
        k = int(input("请给出整数(<%d):" % n))
        k_G = calculate_np(G_x,G_y,k,a,p) # 计算kG
        k_Q = calculate_np(Q[0],Q[1],k,a,p) # 计算kQ
        plain_text = int(input("请输入要加密的明文:"))
        cipher_text = plain_text * k_Q[0]  # 计算明文与kQ横坐标的乘积
        # 密文为
        C = [k_G[0], k_G[1],cipher_text] 
        print("密文为:{(%d,%d),%d}" % (C[0], C[1], C[2]))
        # 解密
        # 计算private_key*kG
        decrypto_text = calculate_np(C[0],C[1],private_key,a,p) 
        
        inverse_value = get_inverse_element(decrypto_text[0], p)
        m = C[2] * inverse_value % p
        print("解密后的明文为%d" % m)
    
        
    if __name__ == '__main__':
        ecc_encrypt_and_decrypt()
    
    

    运行结果

    在这里插入图片描述

    补充

    • 实现过程中,发现斜率不好计算,因为是分数的原因,可以考虑这样计算,假定计算a/b(mod p)可以转换为a/b(mod p) = a * (b的逆元) (mod p)就会大大简化计算。
    • 在编码的过程中,一方面为了使结果更加直观,方便演示,另一方面,因为选择的基点G,必须在椭圆曲线上,所以让椭圆曲线输出整个在Fp域上的点,但是当p取的很大时,就会出现一屏幕输出不下,Fp域,这个时候,可以放弃使用输出整个Fp域,通过计算得到一个点G。
    • 在这个代码实现中,加解密稍微有点不一样,教材中
      加密时:
      选择明文M(x,y)为一个点,而非一个数,而密文为C = (kG,(M+kQ))。计算点C1=M+kQ和C2=kG
      解密时:
      M = C1-dC2
      数学原理为:C1-kC2=M+kQ-dkG=M+kdG-kG-M
      数学原来上能解密是因为:M = C1-dC2=M+kQ-dkG=M+kdG-dkG = M
      当明文为一个数m时,具体原理不变

    博主是一枚进击的小白,难免有错误,如果发现或是有其他建议,请及时提出,进行商讨交流,在此感激不尽

    如果对椭圆曲线原理不清楚,可以查看这篇博客,写的很详细。
    参考链接
    https://www.cnblogs.com/Kalafinaian/p/7392505.html

  • 相关阅读:
    夏普比率(Sharpe Ratio)
    资管产品与信托产品区别
    通道业务是什么业务?怎么做到为银行做资产从表内到表外的流动性搬运?
    什么是MBS,ABS和CDO
    Oracle的OFA架构
    oracle-TNS是什么?
    Windows 如何在cmd命令行中查看、修改、删除与添加环境变量
    oracle的sqlnet.ora,tnsnames.ora,listener.ora三个配置文件
    linux下安装oracle
    金融人物
  • 原文地址:https://www.cnblogs.com/jlxa162hhf/p/14161266.html
Copyright © 2011-2022 走看看