详解Node.js 中使用 ECDSA 签名遇到的坑


Posted in Javascript onNovember 26, 2018

最近有个朋友问我关于 Node.js 下使用 ECDSA 的问题,主要是使用 Node.js 的 Crypto 模块无法校验网络传输过来的签名结果。在踩坑无数后,终于搞清楚了原因。

坑 0x00:签名输出格式

在排除了证书、消息不一致的可能之后,我开始对比使用 Node.js 签名的结果与网络传输过来的签名,发现长度不一致,大约差了5~7个字节。于是去网上搜索了一下,才知道原来 Node.js (基于 OpenSSL)签名得到的是 DER 格式的内容,而网络上常用的 ECDSA 签名结果是 IEEE P1363 格式的。(也可以写作 R|S)

参考:https://stackoverflow.com/a/39575576

知道问题了就好解决了。但是,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)。

参考:https://stackoverflow.com/a/47099047

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript实现校验文件上传控件实例
Apr 20 Javascript
Jquery实现的简单轮播效果【附实例】
Apr 19 Javascript
Bootstrap4一次重大更新 几乎涉及每行代码
May 16 Javascript
JS Select下拉框(支持输入模糊查询)
Feb 04 Javascript
简单实现jQuery弹幕效果
May 06 jQuery
如何使用JS在HTML中自定义字符串格式化
Jul 20 Javascript
vue mintui-Loadmore结合实现下拉刷新和上拉加载示例
Oct 12 Javascript
JavaScript中EventLoop介绍
Jan 22 Javascript
node中的cookie的具体使用
Sep 13 Javascript
django js 实现表格动态标序号的实例代码
Jul 12 Javascript
Nuxt.js 静态资源和打包的操作
Nov 06 Javascript
详解ES6实现类的私有变量的几种写法
Feb 10 Javascript
Vue.js的动态组件模板的实现
Nov 26 #Javascript
解决Vue开发中对话框被遮罩层挡住的问题
Nov 26 #Javascript
Vue项目部署在Spring Boot出现页面空白问题的解决方案
Nov 26 #Javascript
electron制作仿制qq聊天界面的示例代码
Nov 26 #Javascript
Vuex的初探与实战小结
Nov 26 #Javascript
微信小程序页面间值传递的两种方法
Nov 26 #Javascript
Vue中的methods、watch、computed的区别
Nov 26 #Javascript
You might like
坏狼的PHP学习教程之第2天
2008/06/15 PHP
推荐一款MAC OS X 下php集成开发环境mamp
2014/11/08 PHP
Yii框架中memcache用法实例
2014/12/03 PHP
php实现模拟登陆方正教务系统抓取课表
2015/05/19 PHP
Linux安装配置php环境的方法
2016/01/14 PHP
基于PHP制作验证码
2016/10/12 PHP
php使用 readfile() 函数设置文件大小大小的方法
2017/08/11 PHP
PHP性能分析工具xhprof的安装使用与注意事项
2017/12/19 PHP
PHP+fiddler抓包采集微信文章阅读数点赞数的思路详解
2019/12/20 PHP
兼容多浏览器的iframe自适应高度(ie8 、谷歌浏览器4.0和 firefox3.5.3)
2009/11/04 Javascript
JavaScript Event学习第五章 高级事件注册模型
2010/02/07 Javascript
ext combox 下拉框不出现自动提示,自动选中的解决方法
2010/02/24 Javascript
javascript动态加载实现方法一
2012/08/22 Javascript
关于textarea提交的内容无法换行的解决办法
2013/04/09 Javascript
分享28款免费实用的 JQuery 图片和内容滑块插件
2014/12/15 Javascript
JavaScript基础语法之js表达式
2016/06/07 Javascript
jQuery为DOM动态追加事件的方法
2017/02/16 Javascript
Agularjs妙用双向数据绑定实现手风琴效果
2017/05/26 Javascript
AngularJS实现页面跳转后自动弹出对话框实例代码
2017/08/02 Javascript
vue-router 源码之实现一个简单的 vue-router
2018/07/02 Javascript
使用微信小程序开发弹出框应用实例详解
2018/10/18 Javascript
通过扫小程序码实现网站登陆功能
2019/08/22 Javascript
[00:56]PWL开团时刻DAY8——追追追追追!
2020/11/09 DOTA
Python itertools模块详解
2015/05/09 Python
python中子类调用父类函数的方法示例
2017/08/18 Python
java中两个byte数组实现合并的示例
2018/05/09 Python
使用Python向DataFrame中指定位置添加一列或多列的方法
2019/01/29 Python
Python+PyQt5实现美剧爬虫可视工具的方法
2019/04/25 Python
彻底搞懂 python 中文乱码问题(深入分析)
2020/02/28 Python
详解BeautifulSoup获取特定标签下内容的方法
2020/12/07 Python
利用CSS3实现炫酷的飞机起飞动画
2016/09/17 HTML / CSS
Marc Jacobs彩妆官网:Marc Jacobs Beauty
2017/07/03 全球购物
对党的十八届四中全会的期盼
2014/10/17 职场文书
三八妇女节慰问信
2015/02/14 职场文书
银行反洗钱宣传活动总结
2015/05/08 职场文书
伊索寓言读书笔记
2015/06/30 职场文书