详解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 07 Javascript
PHP+jQuery+Ajax+Mysql如何实现发表心情功能
Aug 06 Javascript
jQuery垂直多级导航菜单代码分享
Aug 18 Javascript
AngularJS中处理多个promise的方式
Feb 02 Javascript
浅谈js里面的InttoStr和StrtoInt
Jun 14 Javascript
js 获取当前web应用的上下文路径实现方法
Aug 19 Javascript
node.js 中间件express-session使用详解
May 20 Javascript
Vue.js实现微信过渡动画左右切换效果
Jun 13 Javascript
vue 2.0封装model组件的方法
Aug 03 Javascript
JS高级技巧(简洁版)
Jul 29 Javascript
Vue.js 中的 v-cloak 指令及使用详解
Nov 19 Javascript
js删除数组中某几项的方法总结
Jan 16 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
PHP3 safe_mode 失效漏洞
2006/10/09 PHP
php绘图之在图片上写中文和英文的方法
2015/01/24 PHP
WordPress中Gravatar头像缓存到本地及相关优化的技巧
2015/12/19 PHP
PHP实现简易blog的制作
2016/10/24 PHP
深入理解PHP的远程多会话调试
2017/09/21 PHP
PHP基于PDO扩展操作mysql数据库示例
2018/12/24 PHP
TP框架实现上传一张图片和批量上传图片的方法分析
2020/04/23 PHP
js下通过getList函数实现分页效果的代码
2010/09/17 Javascript
利用原生JavaScript获取元素样式只是获取而已
2014/10/08 Javascript
提交按钮的name='submit'引起的js失效问题及原因
2015/02/25 Javascript
BootStrap智能表单实战系列(三)分块表单配置详解
2016/06/13 Javascript
分享JS代码实现鼠标放在输入框上输入框和图片同时更换样式
2016/09/01 Javascript
扩展bootstrap的modal模态框-动态添加modal框-弹出多个modal框
2017/02/21 Javascript
js中的闭包学习心得
2018/02/06 Javascript
vue+mousemove实现鼠标拖动功能(拖动过快失效问题解决方法)
2018/08/24 Javascript
javascript数据类型中的一些小知识点(推荐)
2019/04/18 Javascript
layer的prompt弹出框,点击回车,触发确定事件的方法
2019/09/06 Javascript
小程序websocket心跳库(websocket-heartbeat-miniprogram)
2020/02/23 Javascript
Vue插槽_特殊特性slot,slot-scope与指令v-slot说明
2020/09/04 Javascript
用Python将动态GIF图片倒放播放的方法
2016/11/02 Python
通过python顺序修改文件名字的方法
2018/07/11 Python
用Python实现读写锁的示例代码
2018/11/05 Python
python3+selenium实现qq邮箱登陆并发送邮件功能
2019/01/23 Python
Python判断对象是否为文件对象(file object)的三种方法示例
2019/04/26 Python
python 用户交互输入input的4种用法详解
2019/09/24 Python
Python正则表达式急速入门(小结)
2019/12/16 Python
opencv 图像加法与图像融合的实现代码
2020/07/08 Python
意大利单身交友网站:Meetic
2020/07/12 全球购物
什么是唯一索引
2015/07/05 面试题
竞聘演讲稿范文
2014/01/12 职场文书
奠基仪式主持词
2014/03/20 职场文书
授权收款委托书范本
2014/10/10 职场文书
入党介绍人意见怎么写
2015/06/03 职场文书
家庭教育教师培训学习体会
2016/01/14 职场文书
python实现腾讯滑块验证码识别
2021/04/27 Python
英镑符号 £
2022/02/17 杂记