伪代码简述 ECDSA 签名过程 | 联盟链开发(十一)

程序员易懂的 ECDSA 原理简述

系列索引: 上链与背后的流程 | 联盟链开发(一) 动手编 SDK | 联盟链开发(二) SDK 1.0 版本的打造 | 联盟链开发(三) 将 SDK 发布到 PIP | 联盟链开发(四) 什么样的数据应该上链?| 联盟链开发 (五) BSN 相关问与答 | 联盟链开发(六) 链上简历应用 — 设计 | 联盟链开发(七) FISCO BCOS 介绍 | 联盟链开发(八) WeIdentity 极速体验 | 联盟链开发(九) 给Remix升个级 | 联盟链开发(十) 伪代码简述 ECDSA 签名过程 | 联盟链开发(十一) WeIdentity 的多签及限量凭证的实现 | 联盟链开发(十二)


在《比特币极速入门指南》一书里,我阐述了公私钥究竟是什么:

  • 私钥的本质: 私钥的本质是一个数字,这个数字用 16 进制表示的话,长度是 64;转换为字节,是 32 字节。
  • 公钥的本质: 用私钥生成Secp256k1曲线上的一个点,将 x 与 y 拼接起来,再在开头加上 <<04>> 后得到一个数字,这个数字就是公钥。用 16进制表示的话,长度是 130;转换为字节,是 65 字节。

地址:

阅读版—— http://dwz.date/a8dY

互动版 —— https://xue.cn/hub/app/books/3

由于是「入门指南」,所以没有对 ECDSA 具体的签名过程进行详细阐述,只做黑箱处理。但是,对于进阶读者而言,了解 ECDSA 签名的实现逻辑还是有其必要的。

在一般介绍 ECDSA 原理的文章中,普遍使用数学语言。虽然非常严谨,但读起来还是比较费劲。所以,今天我在这里,通过伪代码的形式,介绍 ECDSA 的原理,以便大家更好的理解。

首先我们定义这件事儿里有几个角色:

  • 私钥小姐与公钥先生

    我们称其为 priv 与 pub。

  • 要加密的信息 m

    在区块链里一般 m = 交易,不过理论上只要是个东西就能加密。

  • G 点

    G.x 0x79……98

    G.y 0x48……B8

    G.order 0xFF……41

    具体的数值我们可以从网上搜到,但在这里我们不用管它,只要知道 G 点有三个参数:x, y, order 就行了!

接着我们定义两个操作:

  • Point.mult(num, Point)

    点的乘法,参数是一个数字与一个 (x, y) 点,结果是一个点。我们可以把这个操作看做黑箱,而不用去深究这个操作究竟做了些啥。

  • calculate_rem(num1, num2)

    取余操作

  • hash_and_sth(m)

    我们对信息 m 做一些处理,具体咋处理的不用管,结果就是我们能拿 m 验证出来出来的内容是否正确,但不能拿处理出来的内容反推 m —— 传说中的 hash 函数。

我们现在来用伪代码愉快地生成数字签名吧!

数字签名生成过程

  1. gen_k()

我们首先用 gen_k() 函数生成一个取值范围为[1, order-1] 的随机数,称之为 k。

  1. Point.mult(k, G)

Point.mult(k, G) = Q_point = (x, y)。

  1. calculate_rem(x, order)

    calculate_rem(x, order) = r,如果 r 为 0,则回到第一步,重新生成 k。

  2. calculate_s(k, hash_and_sth(m), priv)

    calculate_s(k, hash_and_sth(m), priv) = s,如果 s 为 0,再次重新生成 k。

  3. v = 27 + calculate_rem(y, 2)

    有了 v,我们验签就更快了,不然要遍历好几个点去找哪一个点是对的。具体怎么做的可以暂且不理,有兴趣的话看:

    http://www.secg.org/sec1-v2.pdf

  4. r & s & v = signature

    把三个东西连起来,得到数字签名!

    和比特币存在差异,比特币在 ECDSA 签名后采用了 DER 编码模式,所以比特币的签名长度是不定的,在71 - 73 个字节之前。但是以太坊则使用的标准 ECDSA 流程,所以签名固定为 r(35字节)+ s(35字节)+v (1字节)=71字节。

    此处 1 字节为 8 个二进制位,即 2 个十六进制位,即 0x00 - 0xFF,用十进制表示则是 0 - 255。

    此外,由于签名中存在随机数 k,所以对同一信息用同一私钥,每次签出来的签名也是不一样的!

把上述过程用伪代码表示,则是:

@spec gen_sig(byte32, string) return byte71
def gen_sig(priv, m) do
    q_point=
         gen_k()
            |> Point.mult(G)
  r = calculate_rem(q_point, G.order)

  s = calculate_s(k, hash_and_sth(m), priv)

  v = 27 + calculate_rem(q_point.y, 2)

  return r & s & v
end 

数字签名验签过程……嗯,明日再谈吧(懒~

slogan.jpeg

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2020-05-19 10:43
  • 阅读 ( 394 )
  • 学分 ( 27 )
  • 分类:入门/理论

0 条评论

请先 登录 后评论
李大狗
李大狗

上海对外经贸大学区块链研究中心副主任

21 篇文章, 4147 学分