Node.js 中使用 ECDSA 签名遇到的坑
文/Fenying
最近有个朋友问我关于 Node.js 下使用 ECDSA 的问题,主要是使用 Node.js 的 Crypto 模块无法校验网络传输过来的签名结果。在踩坑无数后,终于搞清楚了原因。
坑 0x00:签名输出格式
在排除了证书、消息不一致的可能之后,我开始对比使用 Node.js 签名的结果与网络传输过来的签名,发现长度不一致,大约差了5~7个字节。于是去网上搜索了一下,才知道原来 Node.js (基于 OpenSSL)签名得到的是 DER 格式的内容,而网络上常用的 ECDSA 签名结果是 IEEE P1363 格式的。(也可以写作 R|S)
知道问题了就好解决了。但是,DER 和 IEEE P1363 两个格式互转也不是那么容易的。
简单科普一下,ECDSA 是指基于 ECC 椭圆加密算法的签名方式,签名结果是两个整数 R 和 S。 R 和 S 一般长度相同,或者接近。如果长度不同,在各自前面补字节 0x00 直到等长。把 R 和 S 以大头字节序表示,然后依次前后拼接,就是所谓 IEEE P1363 格式。
坑 0x01:DER 的整数问题
先来了解一下 ECDSA 的 DER 输出格式,大概如下:
SEQUENCE <LENGTH> INTEGER <INTEGER_LENGTH> <INTEGER_VALUE...> # 整数 R INTEGER <INTEGER_LENGTH> <INTEGER_VALUE...> # 整数 S
其中
-
SEQUENCE
是 DER 数组(串?)标头,用一个字节 0x30 表示 -
<LENGTH>
是 SEQUENCE 的长度,用一个字节表示,不包括标头和这个长度本身 -
INTEGER
是整数标头,用一个字节 0x02 表示 -
<INTEGER_LENGTH>
是整数的字节长度,用一个字节表示。 -
<INTEGER_VALUE>
是整数的内容,以大头字节序表示。
另一个坑我也已经写出来了,不知道有人发现没有?没想到的话,继续往下。
IEEE P1363 格式下,R 和 S 都是等长的。所以只要把 IEEE P1363 格式的签名从中间切分就可以得到 R 和 S 的内容了。而且 IEEE P1363 格式下,R 和 S 也是以大头字节序表示的,因此没有字节序转换问题了。现在,只需要按上面的格式构造一个 DER 即可。
坑 0x01.0:缺少整数前置字节 0x00
我第一次尝试将 IEEE P1363 格式的签名转换成 DER 格式,并没有失败,但是当我换一个签名结果,却失败了……我对比了 DER 和 IEEE P1363 的区别,发现了一个特点,在 DER 格式下,R 和 S 偶尔会有前置字节 0x00,但不是一定的。
查资料后才明白,DER 下没有“无符号整数”之说,也就是说整数都是有符号的。如果 INTEGER 所表示的整数最高字节大于 0x7F,也就是最高位(符号位)为 1,则表示负数。如果要表示正数,必须在前面补一个字节 0x00……
参考 https://bitcointalk.org/index.php?topic=215205.msg2258789#msg2258789
坑 0x01.1:多余的整数前置字节 0x00
在我修改代码后,虽然提高了成功率,可仍然有失败的情况,仔细看了下,原来是因为 IEEE P1363 格式里,R 和 S 可能被补了不止 1 个字节 0x00……
而 DER 下虽然要求补字节 0x00,却是有且只能有一个字节 0x00。
到此,问题都解决了——直到我测试了 521-bit (是的,你没看错,不是 512) 长度的密钥时,完全失败,毫无例外。
坑 0x02:DER SEQUENCE 的长度超过 0x7F
前面说了,<LENGTH>
只能用一个字节表示,这是一个整数,前文我提到的整数正负问题,这里也存在!
即是说,ECDSA 签名使用 DER 输出格式时,如果使用 521-bit (是的,你没看错,不是 512) 长度的密钥时,DER的长度将超出 0x7F,使得 <LENGTH>
变成了负数!
而解决方案不是补字节 0x00,而是用字节 0x81 填充 <LENGTH>
,再在下一个字节用一个无符号整数的表示长度(0 ~ 255)。
(全文完)
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Centos7 Python3.7 执行 RPi.GPIO
一、GPIO介绍 图中箭头所指,焊脚是4方的,表明是物理引脚1。 二、测试硬件连接是否可以 物理引脚1是3.3v电压(火线),39好引脚是GND(零线),连接电阻和二极管,应该是常亮的,如下图连接: 图中:三个电阻,每个是100欧,串联为300欧。二极发光管有正负极之分,长脚为正极,断脚为负极。 三、软件测试(前提已经安装RPi.GPIO) 1.硬件连接图如下:39号引脚和7号引脚(与1好引脚在同一列,第4排) 2.软件控制: 执行如下命令: sudo /usr/local/python371/bin/ipython 输入如下代码: import RPi.GPIO as GPIO GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(4,GPIO.OUT) GPIO.output(4,GPIO.HIGH) # GPIO.output(4,GPIO.LOW) ## 最后执行,将电压降下来 3.效果图如下: 四、遇到的问题: 如果不使用sudo或使用root用户执行,会报错,显示如下: In [4]: GPI...
- 下一篇
(译)React hooks:它不是一种魔法,只是一个数组——使用图表揭秘提案规则
原文地址:https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e 译文:染陌 (Github) 译文地址:https://github.com/answershuto/Blog 转载请著名出处 我是一名hooks API的忠实粉丝,然而它对你的使用会有一些奇怪的约束,所以我在本文中使用一个模型来把原理展示给那些想去使用新的API却难以理解它的规则的人。 警告:Hooks 还处于实验阶段 本文提到的 Hooks API 还处于实验阶段,如果你需要的是稳定的 React API 文档,可以从这里找到。 解密 Hooks 的工作方式 我发现一些同学苦苦思索新的 Hooks API 中的“魔法”,所以我打算尝试着去解释一下,至少从表层出发,它是如何工作的。 Hooks 的规则 React 核心团队在Hooks的提案中提出了两个在你使用Hooks的过程中必须去遵守的主要规则。 请不要在循环、条件或者嵌套函数中调用 Hooks 都有在 React 函数中才去调用 Hooks 后者我觉得是显而易见的,你需...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2配置默认Tomcat设置,开启更多高级功能