椭圆曲线加法乘法

术语介绍

椭圆曲线定义 y^2 = x^3 + ax + b
单位元
逆元(用来实现减法、除法)

群(伽罗瓦)
阿贝尔群
有限域 素数域
欧几里得算法(辗转相除法)
扩展欧几里得算法
循环子群

曲线类型

openssl ecparam -list_curves

加法乘法

普通算法(使用加法实现乘法)

# 椭圆曲线定义
y^2 = x^3 + ax + b , 4a^3 + 27b^20
# 素数域
mod = 0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff
# 椭圆曲线参数 a b
a = 0xfffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc
b = 0x28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93
# 基点
gx = 0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7
gy = 0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0
G = [gx,gy]
# 循环子群的阶
n = 0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123
# 随机数,此数即为私钥。( k*G 即为公钥,知道公钥,以及G点,很难计算出k,这就是椭圆曲线上的离散对数问题)
# k = 0x3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8-1
k = 0x0000000000000000000000000000000000000000000000000000000010000000-1

# mod = 15424654874903
# a = 16546484
# b = 4548674875
# G = [6478678675,5636379357093]
# k = 546768

temp=G

#coding:utf-8
#欧几里得算法求最大公约数
def get_gcd(a, b):
    k = a // b
    remainder = a % b
    while remainder != 0:
        a = b 
        b = remainder
        k = a // b
        remainder = a % b
    return b
    
#改进欧几里得算法求线性方程的x与y
def get_(a, b):
    if b == 0:
        return 1, 0
    else:
        k = a // b
        remainder = a % b       
        x1, y1 = get_(b, remainder)
        x, y = y1, x1 - k * y1          
    return x, y

#返回乘法逆元
def yunsle(a,b):
    #将初始b的绝对值进行保存
    if b < 0:
        m = abs(b)
    else:
        m = b
    flag = get_gcd(a, b)

    #判断最大公约数是否为1,若不是则没有逆元
    if flag == 1:   
        x, y = get_(a, b)   
        x0 = x % m #对于Python '%'就是求模运算,因此不需要'+m'
        #print(x0) #x0就是所求的逆元
        return x0
    else:
        print("Do not have!")

for i in range(0,k):
    print(hex(i))
    if i == 0:
        aaa=(3*pow(G[0],2) + a)
        bbb=(2*G[1])
        if aaa % bbb !=0:
            val=yunsle(bbb,mod)
            y=(aaa*val) % mod
        else:
            y=(aaa/bbb) % mod
    else:
        aaa=(temp[1]-G[1])
        bbb=(temp[0]-G[0])
        if aaa % bbb !=0:
            val=yunsle(bbb,mod)
            y=(aaa*val) % mod
        else:
            y=(aaa/bbb) % mod

    #print y
    Rx=(pow(y,2)-G[0] - temp[0]) % mod
    Ry=(y*(G[0]-Rx) - G[1]) % mod
    temp=[Rx,Ry]
    #print temp

# print(hex(temp[0],hex(temp[1])))
print(hex(temp[0])+ " " + hex(temp[1]))

乘法加速算法

# sm2 参数定义
mod = 0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff
a = 0xfffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc
b = 0x28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93
gx = 0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7
gy = 0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0
G = [gx,gy]
n = 0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123
k = 0xF39C92AAF2E5908357F6B5D0CDAD8D422F4670AC897DA53C38524CD963ACF554-1
# k = 0x0000000000000000000000000000000000000000000000000000000000000044-1

# mod = 15424654874903
# a = 16546484
# b = 4548674875
# G = [6478678675,5636379357093]
# k = 546768

#coding:utf-8
# 欧几里得算法求最大公约数
def get_gcd(a, b):
    k = a // b
    remainder = a % b
    while remainder != 0:
        a = b 
        b = remainder
        k = a // b
        remainder = a % b
    return b
    
# 改进欧几里得算法求线性方程的x与y
def get_(a, b):
    if b == 0:
        return 1, 0
    else:
        k = a // b
        remainder = a % b       
        x1, y1 = get_(b, remainder)
        x, y = y1, x1 - k * y1          
    return x, y

#返回乘法逆元
def yunsle(a,b):
    #将初始b的绝对值进行保存
    if b < 0:
        m = abs(b)
    else:
        m = b
    flag = get_gcd(a, b)

    #判断最大公约数是否为1,若不是则没有逆元
    if flag == 1:   
        x, y = get_(a, b)   
        x0 = x % m #对于Python '%'就是求模运算,因此不需要'+m'
        #print(x0) #x0就是所求的逆元
        return x0
    else:
        print("Do not have!")

def xxx_add(g1,g2):
    # print(hex(g1[0]))
    # print(hex(g2[0]))
    if g1 == g2:
        print("same")
        aaa=(3*pow(g2[0],2) + a)
        bbb=(2*g2[1])
        if aaa % bbb !=0:
            val=yunsle(bbb,mod)
            y=(aaa*val) % mod
        else:
            y=(aaa/bbb) % mod
    else:
        aaa=(g1[1]-g2[1])
        bbb=(g1[0]-g2[0])
        if aaa % bbb !=0:
            val=yunsle(bbb,mod)
            y=(aaa*val) % mod
        else:
            y=(aaa/bbb) % mod
    #print y
    Rx=(pow(y,2)-g2[0] - g1[0]) % mod
    Ry=(y*(g2[0]-Rx) - g2[1]) % mod
    return [Rx,Ry]

# 加速算法
def bits(n):
    while n:
        yield n & 1
        n >>= 1

def double_and_add(n,x):
    result = G
    addend = x
    
    for bit in bits(n):
        if bit == 1:
            result = xxx_add(result,addend)
        addend = xxx_add(addend,addend)
    
    return result

rx = double_and_add(k,G)

print("result:")
print(hex(rx[0]))
print(hex(rx[1]))

参考链接

椭圆曲线加密与NSA后门考古
椭圆曲线加密中的加法乘法浅析 参考链接值得一读
椭圆曲线加法演示
SM2国密算法/椭圆曲线密码学ECC之数学原理

posted @   nikoladi  阅读(595)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示