IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> libsecp256k1比特币密码算法开源库(六) -> 正文阅读

[区块链]libsecp256k1比特币密码算法开源库(六)

2021SC@SDUSC


从本篇开始我将开始分析libsecp256k1中的代码。本开源库可以实现:
私钥经标量乘法生成公钥;
私钥签名(ECDSA);
公钥验证签名;
从签名消息中恢复公钥;
共享私钥(ECDH)
在这一篇中,我将对有限域和椭圆曲线的定义代码和椭圆曲线的几何加法和标量乘法运算进行分析。由于本人目前对这个项目整体认识不足,所以这一篇会随着我对后续代码细节理解的加深随时更改,后续的几篇会详细分析secp256k1开源库实现上述五个功能的代码段以及所用到的各种算法。
这个开源库使用rust语言编写,本人目前正在自学rust。目前阅读代码重点在于明白其中使用的各种算法和数据结构,理解这个开源库的各种功能,因此代码的分析不会强调语法的细枝末节。

有限域Galois Field

定义有限域的秩p以及模p运算

trait curve {
   fn p() ->BigInt ;
   //这里的p就是有限域的秩p
   }
   
struct Field<C: Curve >(BigInt);

impl<C: Curve> Field<C>{
   //将一个元素放入到有限域中,要进行mod p运算
   fn new( v: BigInt ) -> Self{
   Self( v.mod_floor (C::p()))
   }
}

椭圆曲线Elliptic Curves

定义椭圆曲线的三个参数:

//有限域椭圆曲线方程的三个参数a、b、p
use num_bigint::BigInt;
pub trait Curve {
   fn p() -> BigInt ;
   fn a() -> BigInt ;
   fn b() -> BigInt ;
}

具体到secp256k1椭圆曲线的三个参数值:

//定义secp256k1的三个参数a、b、p的值
struct P256K1Curve;

impl Curve for P256K1Curve {
      fn p() -> BigInt {
      BigInt::from_str_radix("FFFFFFFFFFFFFFFF
                              FFFFFFFFFFFFFFFF
                              FFFFFFFFFFFFFFFF
                              FFFFFFFEFFFFFC2F" ,16).unwrap()
      }//定义p取值为以上256位二进制数
      fn a() -> BigInt { BigInt::zero() }//定义a为0
      fn b() -> BigInt { BigInt::from(7u32) }//定义b为7,u32表示无符号int基本整数类型
}

定义椭圆曲线上的点,要么是一个无穷远点,要么就具有x值和y值:

pub enum PointValue {
  Infinity ,  //无穷远点
  Value {
  x: BigInt ,
  y: BigInt ,
  } //定义横纵坐标x和y
}

pub struct Point<C:Curve> {
  pub value: PointValue,
  _marker: PhantomData<C>,
  }

判断任意一个点是不是在椭圆曲线上:

impl<C:Curve> Point<C>{
   pub fn is_valid(&self) -> bool {
   match self.value {
    PointValue::Infinity => true, //如果是一个无穷远点,那么在椭圆曲线上
    PointValue::Value { ref x, ref y } => {
    (y * y - (x * x * x + &C::a() * x + &C::b()))
     .mod_floor(&C::p()) == BigInt::zero() },//如果不是无穷远点,就将该点的横纵坐标代入有限域下椭圆曲线方程检验
   } 
 }
}

椭圆曲线几何加法

进行椭圆曲线P和Q的几何加法主要分几种情况讨论:
P或Q中有一个是无穷远点;
P和Q是同一个点,横纵坐标一致;
P和Q是相反的点,即在图像上关于直线y=p/2对称;
P和Q是除上面三种情况外的一般点

如果其中一个P或者Q是无穷远点,将不是无穷远点的点的横纵坐标返回

impl<C: Curve> Add for Point<C> {
   fn add (self, other: Point<C>) -> Point <C> {
     let (ox, oy) = match other.value {
        PointValue::Infinity => return self ,
        PointValue::Value { ref x, ref y } => (x.clone(), y.clone()),};
     let (sx, sy) = match self.value {
        PointValue::Infinity => return other ,
        PointValue::Value { ref x, ref y } => (x.clone(), y.clone()),};
        ......
   }
}

P和Q横坐标一致时:
如果P和Q是相反的点,那么两点的纵坐标之和等于p,模p的结果为0,可以直接返回结果为无穷远点;
如果P和Q是相同的点,那么两点的纵坐标之和模p的结果一定不为0,就对自身(P或Q)取二倍。

impl<C: Curve> Add for Point <C> {
  fn add(self, other: Point<C>) -> Point <C> {
    ...
    if sx == ox {
       return if (sy + oy ).mod_floor(&C::p()) == BigInt::zero() {
         Point::infinity ()
         }else {
         self.double ()
         }
    }
    ...
  }
}

如果P和Q是一般点
先求斜率l,P点纵坐标减Q点纵坐标再乘以P点横坐标减Q点横坐标模p的乘法逆元,最后结果再对p取模。即( ( yP - yQ) ( xP - xQ )^ -1 ) mod p
再分别求出R的横纵坐标
xR = ( m^2 - xP - xQ ) mod p
yR = ( m (xP - xR) - yP ) mod p

impl<C: Curve > Add for Point<C> {
  type Output = Point <C>;
  fn add(self, other: Point <C>) -> Point<C> {
    ...
    let l = ((&oy - &sy) * utils::inverse_mod(&ox -&sx, C::p())).mod_floor (&C::p());
    let x3 = (&l * &l - &sx - &ox).mod_floor ( &C::p());
    let y3 = (&l *(&sx - &×3) - &sy ) .mod_floor ( &C::p());
    Self::from(PointValue::Value { x: x3, y: y3 })
    }
}

椭圆曲线标量乘法

对椭圆曲线上一点计算标量乘法,如果该点乘的系数n为0,那么返回结果直接就为无穷远点;否则让该点不断与自己做几何加法运算,直到n次结束。

impl<C: Curve> Mul<BigInt> for Point <C> {
  fn mul(self, n: BigInt) -> Point<C> {
    if n == 0 {
      Self::infinity ()
    }else {
     let mut ret = self.clone();
     for _ in 1 ... n {
        ret = ret + self.clone ();
        }
        ret
     }
  }
}

在secp256k1中被计算标量乘法的(也就是椭圆曲线群的生成元)基准点G的横纵坐标。

let g = Point::<P256K1Curve>::from(PointValue::Value {
  x: BigInt::from_str_radix(
  "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",16).unwrap(),
  y: BigInt::from_str_radix(
  "483ADA7726A3C4655DA4FBFCOE1108A8FD17B448A68554199C47D08FFB1004B8",16).unwrap()
});

基准点G进行标量乘法(系数n=3,即三次几何加法运算)得到新的点:

assert.eq!(
  g.clone() *BigInt::from(3u32),
  Point::<P256K1Curve>::from(PointValue::Value {
    x: BigInt::from_str_radix(
  "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",16).unwrap(),
    y: BigInt::from_str_radix(
  "388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672",16).unwrap()
  })
);
  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2021-10-22 10:59:20  更:2021-10-22 10:59:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:36:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码