Appearance
ECC
数学基础
椭圆曲线
形如
常见曲线参数:
secp256k1:
P-256(FIST):
BLS128_381:
二次扩域: SM2:
BN128(zk-snark):
一些特殊曲线
Baby Jubjub Elliptic Curve(扭曲爱德华曲线方程):
- 对于运算
,运算如下:
- 对于运算
点加法
对于椭圆曲线上的两个不同点
斜率计算:
新点坐标:
数学推导
直线方程:通过
和 的直线: 其中
求交点:将直线方程代入椭圆曲线
: 展开得:
整理为三次方程:
根的关系:设三个根为
,由韦达定理: 因此:
y坐标计算:将
代入直线方程得到交点,然后取其关于x轴的对称点:
倍乘运算
当
斜率计算:
新点坐标:
数学推导同上
标量乘法
标量乘法
输入:点 P,标量 k
输出:k·P
1. 初始化 Q = O (无穷远点)
2. 将 k 表示为二进制
3. 从最低位开始:
- 如果当前位为1,则 Q = Q + P
- P = 2P (点倍乘)
- 移到下一位
4. 返回 QECDH(密钥交换)
密钥生成
私钥生成
私钥
公钥生成
公钥
密钥交换
Alice 和 Bob 通过以下步骤交换密钥:
- Alice 生成私钥
和公钥 ,将 发送给 Bob。 - Bob 生成私钥
和公钥 ,将 发送给 Alice。 - Alice 接收到
后,计算共享密钥: - Bob 接收到
后,计算共享密钥: - 最终得到相同共享密钥
。
ECIES(公钥加密)
密钥生成
私钥生成
私钥
公钥生成
公钥
加密过程
给定消息
- 生成随机数
,满足 。 - 计算点
。 - 计算公钥
。 - 生成对称密钥
,其中 是哈希函数。 - 加密消息
。 - 输出密文
。 - 发送密文
给接收方。
解密过程
给定密文
- 计算共享密钥
。 - 生成对称密钥
。 - 解密消息
。 - 输出明文
。
ECDSA(签名)
域参数
:有限域的大小 :椭圆曲线参数 :基点(生成元) :基点的阶(即 )
密钥生成
私钥生成
私钥
公钥生成
公钥
其中
签名生成
给定消息的哈希值
步骤1:生成随机数
生成一个随机数
!!!:这里是简化的,具体参照这里,简单说就是
步骤2:计算点
计算椭圆曲线点:
步骤3:计算 r
!!!:取点
步骤4:计算 s
!!!:
是 在模 下的乘法逆元 将消息哈希与私钥信息结合 - 整个表达式确保了签名与私钥和消息的绑定关系
如果
步骤5:输出签名
签名为
签名验证
给定消息哈希
步骤1:参数验证
验证
步骤2:计算逆元
计算
步骤3:计算标量
步骤4:计算验证点
步骤5:验证结果
如果
数学原理
从签名生成有:
重排得到:
在验证过程中:
替换
由于
根据签名生成中(式
这证明了验证点
Add-On v的生成与公钥恢复
由于压缩传输空间的需要以及ECDSA可以从签名恢复公钥的性质,往往只传输
// TODO
进阶:椭圆曲线计算加速
Jacobian坐标
由于椭圆曲线是
在椭圆曲线上,我们定义单位元为无穷远点 py_ecc.secp256k1里看的)
- 仿射
射影: - 射影
仿射:
而对于实际应用中常使用Jacobian坐标,其转换如下:
- 仿射
Jacobian: - Jacobian
仿射:
注意这里所有的运算都是在mod p下的
加法
注意这里所有的运算都是在mod p下的
对于
如果
倍乘
注意这里所有的运算都是在mod p下的
(里面的
注意倍乘时可以用类似平方快速幂的方式加速
python
if a[1] == 0 or n == 0:
return cast("PlainPoint3D", (0, 0, 1))
if n == 1:
return a
if n < 0 or n >= N:
return jacobian_multiply(a, n % N)
if (n % 2) == 0:
return jacobian_double(jacobian_multiply(a, n // 2))
if (n % 2) == 1:
return jacobian_add(jacobian_double(jacobian_multiply(a, n // 2)), a)
raise ValueError("Unexpected case in jacobian_multiply: This should never happen.")扩展域
// TODO