详解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 相关文章推荐
分享XmlHttpRequest调用Webservice的一点心得
Jul 20 Javascript
JQuery中阻止事件冒泡几种方式及其区别介绍
Jan 15 Javascript
jquery自定义插件——window的实现【示例代码】
May 06 Javascript
AngularJS 简单应用实例
Jul 28 Javascript
BootStrap下拉框在firefox浏览器界面不友好的解决方案
Aug 18 Javascript
JavaScript字符串检索字符的方法
Jun 23 Javascript
利用JS测试目标网站的打开响应速度
Dec 01 Javascript
JS求Number类型数组中最大元素方法
Apr 08 Javascript
mpvue全局引入sass文件的方法步骤
Mar 06 Javascript
Nuxt.js实战和配置详解
Aug 05 Javascript
js简单实现自动生成表格功能示例
Jun 02 Javascript
微信小程序实现签到弹窗动画
Sep 21 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
ThinkPHP之getField详解
2014/06/20 PHP
PHP中Http协议post请求参数
2015/11/02 PHP
基于PHP+mysql实现新闻发布系统的开发
2020/08/06 PHP
JS之小练习代码
2008/10/12 Javascript
面向对象的javascript(笔记)
2009/10/06 Javascript
js multiple全选与取消全选实现代码
2012/12/04 Javascript
JQuery实现绚丽的横向下拉菜单
2013/12/19 Javascript
JQuery实现当鼠标停留在某区域3秒后自动执行
2014/09/09 Javascript
JS选项卡动态替换banner图片路径的方法
2015/05/11 Javascript
JS+CSS实现经典的左侧竖向滑动菜单效果
2015/09/23 Javascript
浅谈Javascript事件对象
2017/02/05 Javascript
微信小程序实现带刻度尺滑块功能
2017/03/29 Javascript
react.js 获取真实的DOM节点实例(必看)
2017/04/17 Javascript
JS失效 提示HTML1114: (UNICODE 字节顺序标记)的代码页 utf-8 覆盖(META 标记)的冲突的代码页 utf-8
2017/06/23 Javascript
提升node.js中使用redis的性能遇到的问题及解决方法
2018/10/30 Javascript
vue-cli4.0多环境配置变量与模式详解
2020/12/30 Vue.js
[51:15]2014 DOTA2国际邀请赛中国区预选赛 Orenda VS LGD-GAMING
2014/05/22 DOTA
zbar解码二维码和条形码示例
2014/02/07 Python
Python输出9*9乘法表的方法
2015/05/25 Python
Python的时间模块datetime详解
2017/04/17 Python
Python实现通过文件路径获取文件hash值的方法
2017/04/29 Python
tornado 多进程模式解析
2018/01/15 Python
详解Python中is和==的区别
2019/03/21 Python
Django模型序列化返回自然主键值示例代码
2019/06/12 Python
python实现Pyecharts实现动态地图(Map、Geo)
2020/03/25 Python
Python中socket网络通信是干嘛的
2020/05/27 Python
ASOS英国官网:英国在线时装和化妆品零售商
2017/05/19 全球购物
师范应届生语文教师求职信
2013/10/29 职场文书
理工科学生的自我评价
2013/12/15 职场文书
公司晚会主持词
2014/03/22 职场文书
班主任班级寄语大全
2014/04/04 职场文书
小学教师先进事迹材料
2014/12/15 职场文书
干部考察材料范文
2014/12/24 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
趣味运动会新闻稿
2015/07/17 职场文书
python文本处理的方案(结巴分词并去除符号)
2021/05/26 Python