详解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 相关文章推荐
网站上面有这种切换效果
Jun 26 Javascript
在多个页面使用同一个HTML片段的代码
Mar 04 Javascript
Javascript中的arguments与重载介绍
Mar 15 Javascript
JavaScript中的getTimezoneOffset()方法使用详解
Jun 10 Javascript
jquery实现点击向下展开菜单项(伸缩导航)效果
Aug 22 Javascript
基于jquery实现的树形菜单效果代码
Sep 06 Javascript
js实现select下拉框菜单
Dec 08 Javascript
Angular2 之 路由与导航详细介绍
May 26 Javascript
详解Angular Reactive Form 表单验证
Jul 06 Javascript
jQuery选择器选中最后一个元素,倒数第二个元素操作示例
Dec 10 jQuery
Bootstrap Paginator+PageHelper实现分页效果
Dec 29 Javascript
谈谈为什么你的 JavaScript 代码如此冗长
Jan 30 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
ajax php 实现写入数据库
2009/09/02 PHP
PHP读取txt文件的内容并赋值给数组的代码
2011/11/03 PHP
基于PHP CURL获取邮箱地址的详解
2013/06/03 PHP
php实现设计模式中的单例模式详解
2014/10/11 PHP
PHP解析目录路径的3个函数总结
2014/11/18 PHP
PHP ADODB生成下拉列表框功能示例
2018/05/29 PHP
PHP设计模式(四)原型模式Prototype实例详解【创建型】
2020/05/02 PHP
JQuery 前台切换网站的样式实现
2009/06/22 Javascript
style、 currentStyle、 runtimeStyle区别分析
2010/08/01 Javascript
jQuery方法简洁实现隔行换色及toggleClass的使用
2013/03/15 Javascript
JavaScript分页功能的实现方法
2015/04/25 Javascript
jquery插件jSignature实现手动签名
2015/05/04 Javascript
javascript伸缩菜单栏实现代码分享
2015/11/12 Javascript
超链接怎么正确调用javascript函数
2016/05/23 Javascript
JS中传递参数的几种不同方法比较
2017/01/20 Javascript
JS写谷歌浏览器chrome的外挂实例
2018/01/11 Javascript
[22:59]VGJ.S vs VG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[49:05]OG vs Newbee 2019DOTA2国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21.mp4
2020/07/19 DOTA
Django视图之ORM数据库查询操作API的实例
2017/10/27 Python
Flask-WTF表单的使用方法
2019/07/12 Python
Python判断三段线能否构成三角形的代码
2020/04/12 Python
Python使用内置函数setattr设置对象的属性值
2020/10/16 Python
德国购买健身器材:AsVIVA
2017/08/09 全球购物
俄罗斯品牌服装和鞋子的在线商店:KUPIVIP
2019/10/27 全球购物
泰国国际航空公司官网:Thai Airways International
2019/12/04 全球购物
西部世纪面试题
2014/12/05 面试题
管理心得体会
2013/12/28 职场文书
旷课检讨书3000字
2014/02/04 职场文书
普通大学毕业生自荐信范文
2014/02/23 职场文书
董事长助理工作职责
2014/06/08 职场文书
北京奥运会口号
2014/06/21 职场文书
拒绝黄毒毒宣传标语
2014/06/26 职场文书
试用期解除劳动合同通知书
2015/04/16 职场文书
社会主义核心价值观主题教育活动总结
2015/05/07 职场文书
大学军训口号大全
2015/12/24 职场文书
Vue.js 带下拉选项的输入框(Textbox with Dropdown)组件
2021/04/17 Vue.js