1 简介

⽐特币基于椭圆曲线加密的椭圆曲线数字签名算法(ECDSA),特定的椭圆曲线称为secp256k1。其公式定义如下

y2=x3+ax+b mod p

其中:p = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F = 2256-232-29-28-27-26-24-1 = 2256-232-977,a = 0, b=7

基点G为:x=0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,y=0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8

G的阶为:n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

secp256k1的命名出自一个密码协议标准,每一个字母和数字都代表着特定含义,下面分别进行介绍

1.1 密码协议标准

第一部分是「sec」,sec是Standards for Efficient Cryptography 的简称,是SECG发布的一种密码学协议标准。SECG发布的「SEC 1」和「SEC 2」两个关于椭圆曲线的协议标准,在「SEC 2」中有详细说明secp256k1以及其他曲线的参数定义。除了「sec」,还有众多其他关于椭圆曲线的协议标准,从SafeCurve中可以看到有下列不同类型的标准。

「SafeCurve」此处较久没有更新,有些标准已经更新了多次,例如NIST关于数字签名的标准 FIPS 186目前在用的是第四版,第五版也在起草中了,从「NIST」官网中可见。

1.2 有限域

第二部分是「p」,p表示该椭圆曲线是基于素数有限域Fp。有限域是离散数学中的概念,它是一个由有限数量元素组成的集合,元素之间可以进行加法和乘法计算。密码学中使用椭圆曲线都是基于有限域的,除了素数有限域Fp之外,还有另一种特征为2的有限域F2m,Fp的大小(元素个数)为p,F2m的大小为2m。基于Fp的椭圆曲线为:

基于F2m的椭圆曲线为:

在「SEC 2」中还定义了sect163k1、sect163r1等曲线,其中,t表示的是该曲线基于F2m。在「NIST FIPS 186-4」中定了P-256、B-163等曲线,P-表示基于Fp,B-表示基于F2m

1.3 有限域大小

每个椭圆曲线E都有若干关键参数,包括阶为n的基点G和协因子h等,其中,n为一个大素数,n*h为椭圆曲线上点的数量。为了计算效率考虑,h通常设置为1、2或4。通俗地讲,如果椭圆曲线上的点数量越多,那么这条椭圆曲线的安全度就越高,因此n的取值是影响曲线安全的关键。椭圆曲线又都是基于有限域的,曲线上的点都是有限域中的元素,因此,有限域大小决定了曲线安全度。第三部分「256」就是有限域大小的表现形式,还有更多其他如192、224、384等,在「NIST FIPS 186-4」中有个表格展现了Fp 和F2m两个域的各种不同大小配置。

SEC标准在这块的设置和NIST标准类似,我们会看到p系列的曲线有p192、p224、p256(secp256k1就是其中一种)、p384和p521,t/B系列有t163/B-163、t233/B-233等。

1.4 Koblitz Curve

第四部分「k」表示该曲线是Koblitz Curve(科布利兹曲线),从「SEC 2」中可以看到还有此处标记为r的曲线(如secp256r1),r表示该曲线是伪随机曲线Pseudo-Random Curve。Koblitz Curve命名源自数学家「Neal Koblitz」,它是一种特殊的曲线,它的一些参数是精心挑选设置的。Koblitz Curve具有自同态的性质,可以通过优化大幅提升计算效率。相比之下,Pesudo-Random Curve的对应参数是通过随机种子计算出来的,有标准的检验算法可以检测所有参数是随机种子产生而来。在「NIST FIPS 186-4」中Koblitz Curve曲线以「K-」标记开头,分别有K-163、K-233等。

1.5 末位标记

到了第五部分「1」,这是代表在前4个条件下提供了多种推荐参数设置,在SEC标准中大部分该位都是1,即只提供一种推荐参数,sect163r2是一个例外。下面把SEC和NIST两个标准推荐的曲线分别列一下,二者有较大部分是相同的参数设置。

上述表格中,同一行中SEC和NIST都出现的,两个曲线虽然名字不同,但参数完全相同,也就是说其实一样的。橙色底纹的几个SEC曲线没有对应的NIST曲线,因此SEC标准包含的曲线比NIST多一些,如这里secp256k1就是SEC标准单独存在的。说到这里,不得不提一个正经八卦。据说,NIST推荐的Pesudo-Random Curve,也就是P和B系列,并没有公布随机数挑选规则,外界存在一种疑虑,可能NSA(美国国家安全局)掌握了后门,能够轻易破解这些密码协议。

2  源码及编译

secp256k1源码可以从以下地址下载:https://github.com/bitcoin-core/secp256k1

用git下载源码

git clone https://github.com/bitcoin-core/secp256k1

Check out最新release版本

git checkout v0.6.0

2.1 Linux下编译

在Linux下可以使用Autotools进行编译

$ ./autogen.sh       # Generate a ./configure script
$ ./configure # Generate a build system
$ make # Run the actual build process
$ make check # Run the test suite
$ sudo make install # Install the library into the system (optional)

可以用./configure --prefix=指定安装路径,如我将编译结果安装到buildout目录下,其目录结构如下:

2.2 Windows编译

在Windows下,使用CMake+VS2019进行编译,编译配置如下:

Generate时使用默认配置,完成后用VS2019打开生成好的工程,进行编译,结果如下:

运行其中的tests项目输出如下:

由于内容比较多,所以运行花费时间较长。

3 应用

用VS2019创建控制台应用程序secp256k1Test,并将include和之前编译生成lib库及dll库放到工程目录下

按照以上目录结构,修改项目C/C++中的包含路径及链接器中的配置

主程序secp256k1Test.c如下

 1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include "secp256k1.h"
6
7 #define bswap_16(value) \
8 ((((value) & 0xff) << 8) | ((value) >> 8))
9
10 #define bswap_32(value) \
11 (((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \
12 (uint32_t)bswap_16((uint16_t)((value) >> 16)))
13
14 #define bswap_64(value) \
15 (((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) \
16 << 32) | \
17 (uint64_t)bswap_32((uint32_t)((value) >> 32)))
18
19 int main()
20 {
21 int ret;
22 secp256k1_context* pCtx = NULL;
23 secp256k1_pubkey pubkey;
24 unsigned char rand32[32] = { 0 };
25 printf("this is for secp256k1 testing\n");
26
27 pCtx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
28 if (pCtx) {
29 for (int i = 0; i < sizeof(rand32) / 4; i++) {
30 int r = rand();
31 memcpy(rand32 + i * 4, &r, 4);
32 }
33 if (!secp256k1_context_randomize(pCtx, rand32))
34 printf("secp256k1_context_randomize failed\n");
35 else {
36 printf("secp256k1_context_randomize success\n");
37 }
38
39 memset(rand32, 0, sizeof(rand32));
40 rand32[31] = 1;
41 ret = secp256k1_ec_pubkey_create(pCtx, &pubkey, rand32);
42 if (ret) {
43 printf("private key\n0x");
44 for (int i = 0; i < 32; i++)
45 printf("%02x", rand32[i]);
46 printf("\n");
47 printf("secp256k1_ec_pubkey_create success\n");
48 printf("0x");
49 for (int i = 0; i < 32; i++)
50 printf("%02x", pubkey.data[31-i]);
51 printf("\n0x");
52 for (int i = 0; i < 32; i++)
53 printf("%02x", pubkey.data[63-i]);
54 printf("\n");
55 }
56 else {
57 printf("secp256k1_ec_pubkey_create failed\n");
58 }
59
60 // order N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
61 unsigned int* pData = (unsigned int*)rand32;
62 pData[0] = bswap_32(0xFFFFFFFF);
63 pData[1] = bswap_32(0xFFFFFFFF);
64 pData[2] = bswap_32(0xFFFFFFFF);
65 pData[3] = bswap_32(0xFFFFFFFE);
66 pData[4] = bswap_32(0xBAAEDCE6);
67 pData[5] = bswap_32(0xAF48A03B);
68 pData[6] = bswap_32(0xBFD25E8C);
69 pData[7] = bswap_32(0xD0364140);
70 ret = secp256k1_ec_pubkey_create(pCtx, &pubkey, rand32);
71 if (ret) {
72 printf("private key\n0x");
73 for (int i = 0; i < 32; i++)
74 printf("%02x", rand32[i]);
75 printf("\n");
76 printf("secp256k1_ec_pubkey_create success\n");
77 printf("0x");
78 for (int i = 0; i < 32; i++)
79 printf("%02x", pubkey.data[31 - i]);
80 printf("\n0x");
81 for (int i = 0; i < 32; i++)
82 printf("%02x", pubkey.data[63 - i]);
83 printf("\n");
84 }
85 else {
86 printf("secp256k1_ec_pubkey_create failed\n");
87 }
88
89 secp256k1_context_destroy(pCtx);
90 }
91
92 return 1;
93 }

secp256k1Test.c

程序第40,41行,以0x1为私钥产生公钥,即椭圆曲线生成元G。程序第62~70行, 以阶n-1为私钥产生公钥,即(n-1)*G,这里仅为测试,所以两次取的私钥都是特殊值,正常情况下私钥要随机产生,程序最终运行结果如下

this is for secp256k1 testing
secp256k1_context_randomize success
private key
0x0000000000000000000000000000000000000000000000000000000000000001
secp256k1_ec_pubkey_create success
0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
private key
0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140
secp256k1_ec_pubkey_create success
0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
0xb7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777

有椭圆曲线理论可知两次产生的公钥点互为逆元,它们关于x轴对称,x坐标相同,y坐标互为相反数(在有限域内y坐标之和为模数p)。

参考:

https://cloud.tencent.com/developer/news/586021

secp256k1算法详解一的更多相关文章

  1. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  2. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

  3. 机器学习经典算法详解及Python实现--基于SMO的SVM分类器

    原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector  ...

  4. [转] KMP算法详解

    转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段.    我们这里说的K ...

  5. 【转】AC算法详解

    原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和 ...

  6. KMP算法详解(转自中学生OI写的。。ORZ!)

    KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句 ...

  7. EM算法详解

    EM算法详解 1 极大似然估计 假设有如图1的X所示的抽取的n个学生某门课程的成绩,又知学生的成绩符合高斯分布f(x|μ,σ2),求学生的成绩最符合哪种高斯分布,即μ和σ2最优值是什么? 图1 学生成 ...

  8. Tarjan算法详解

    Tarjan算法详解 今天偶然发现了这个算法,看了好久,终于明白了一些表层的知识....在这里和大家分享一下... Tarjan算法是一个求解极大强联通子图的算法,相信这些东西大家都在网络上百度过了, ...

  9. 安全体系(二)——RSA算法详解

    本文主要讲述RSA算法使用的基本数学知识.秘钥的计算过程以及加密和解密的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 1.概述 ...

  10. 安全体系(三)——SHA1算法详解

    本文主要讲述使用SHA1算法计算信息摘要的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 安全体系(二)——RSA算法详解 为保 ...

随机推荐

  1. weblogic日志查看

    都是使用tail -f catalina.out命令来查看的,不要太顺手: 今天登陆到公司另外一个Team 的服务器上,发现装的是weblogic,手痒想看看weblogic怎么看日志,找了老半天,才 ...

  2. [源码系列:手写spring] IOC第二节:BeanDefinition和BeanDefinitionRegistry

    主要内容 BeanDefinition:顾名思义,就是类定义信息,包含类的class类型.属性值.方法等信息. BeanDefinitionRegistry:添加BeanDefinitionRegis ...

  3. [源码系列:手写spring] IOC第一节:简单bean容器

    本专栏带领大家手写一遍spring的核心代码,包括IOC,AOP,三级缓存... 第一节较为简单,后面的章节会逐渐提升代码量和复杂度,喜欢的同学记得订阅哦  ̄▽ ̄ 定义一个简单的bean容器BeanF ...

  4. 泛型--java进阶day10

    1.泛型 2.泛型--统一数据类型 如下图,当我们在泛型中添加不同的数据类型,add方法需要的数据类型也随之改变 [1] [2] 泛型--默认类型object 当我们不指定泛型时,泛型的默认类型为ob ...

  5. CompletableFuture原理及应用场景详解

    1.应用场景 现在我们打开各个APP上的一个页面,可能就需要涉及后端几十个服务的API调用,比如某宝.某个外卖APP上,下面是某个外卖APP的首页.首页上的页面展示会关联很多服务的API调用,如果使用 ...

  6. Graph4Stream:基于图的流计算加速

    作者:汪煜 之前在「姊妹篇」<Stream4Graph:动态图上的增量计算>中,向大家介绍了在图计算技术中引入增量计算能力「图+流」,GeaFlow流图计算相比Spark GraphX取得 ...

  7. nodejs终端字符样式和进度条

    Nodejs为终端字符增加样式 只有黑白的色调对于比较复杂的命令行程序来说就显得太单调了,我们可以为命令行程序增加样式使得程序更加友好! 安装package: npm install -S chalk ...

  8. Sql Server数据库远程连接访问设置

    步骤一:设置sql server数据库 1.以新建一个新用户名test作为远程连接登录名.在本地登录sql server数据库,安全性->右键用户名 2.点击根目录右键,选择属性 选择安全性 选 ...

  9. C#之值类型与引用类型--out参数--ref参数-"=="、Equals和ReferenceEquals之间的区别

    一.值类型和引用类型 1.值类型 (1)值类型的大小是固定的 (2)值类型都派生自ValueType (3)值类型不能继承,只能实现接口 2.值类型:int.char.double.float.lon ...

  10. 一条 SQL 语句在 MySQL 中的执行过程

    一条 SQL 语句在 MySQL 中的执行过程 当一条 SQL 语句被提交到 MySQL 时,它会经历多个步骤,包括解析.优化.执行等.以下以 SELECT 语句为例,详细描述整个执行流程. 1. 客 ...