区块链基础编程 - 椭圆曲线密钥
以下为翻译文章,英文原版链接在这里,文章中的“我”指的是原文作者
通过代码生成密钥对
密钥对的生成工序比较繁琐,然而通过OpenSSL这个库来操作的话,也不是那么困难。我在ec.h写了一个辅助方法,他的声明如下:
1
|
|
我们现来一起分析其中的一部分代码。代码涉及到OpenSSL中的一些数据结构:
- BN_CTX, BIGNUM
- EC_KEY
- EC_GROUP, EC_POINT
前两个结构属于OpenSSL中任意精度运算的领域,它们的作用是处理非常大的数字。其它类型都和EC加密有关。EC_KEY可以是完整的密钥对(私钥+公钥),也可以只包含公钥,EC_GROUP和 EC_POINT这两个数据结构就用来帮助我们从私钥计算得出公钥。
最重要的一点是,我们通过创建一个EC_KEY数据结构来操作密钥对:
1
|
|
加载私钥比较容易,但是需要一个中间步骤。在给密钥对提供priv_bytes这个输入之前,我们需要把它转化成一个BIGNUM,这里给它命名为priv:
1 2 3 |
|
对于复杂的大数字运算,OpenSSL需要一个环境,这就是为什么也要创建BN_CTX。公钥的推到过程需要更深的对EC数学原理的理解,这个当然不是本文的目的。简要的说,我们首先在曲线上找一个固定点G(这个曲线就是代码中的group变量,也称生成器),然后把这个点的值乘与私钥的标量值n,这实质上是一个不可逆的模运算。它的结果P=n*G就得出第二个点的位置,也就对应公钥pub。最终我们把公钥也加载到密钥对中:
1 2 3 4 5 6 7 |
|
注意:这段代码经过了简化,没有检测是否有调用错误
例子
终于到了测试密钥对的时候了,代码在ex-ec-keypair.c文件里。我们希望代码的输出结果能和直接从命令行用openssl命令得出的结果保持一致。我们令priv_bytes存放我们的私钥:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
测试过程是这样的:
- 通过priv_bytes初始化一个EC_KEY作为密钥对
- 通过一个BIGNUM再把私钥存入priv变量
- 把推导出的公钥存入pub变量,保证这个公钥具备所有通信格式
第三部是最复杂的。首先需要配置通信格式,这个格式会反过来影响公钥的长度(长度可以是33或者65)。实际长度是通过用一个空参数调用i2o_ECPublicKey方法来获取的,目的是让pub分配到足够多的字符空间来存放输出。i2o_ECPublicKey最终把公钥从内部定义的数据结构转化为8位字节数组,这既是为什么这个方法的以i2o开头(octet是字节的意思)。这些经编码后的字节最后通过pub_copy零时变量存入key变量。
请读者自己尝试允许这个程序并和openssl在命令行下的输出做对比