详解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 相关文章推荐
GreyBox技术总结(转)
Nov 23 Javascript
30个最好的jQuery 灯箱插件分享
Apr 25 Javascript
javascript开发技术大全-第1章javascript概述
Jul 03 Javascript
jQuery.each()用法分享
Jul 31 Javascript
jQuery焦点控制图层展示延迟隐藏的方法
Mar 09 Javascript
jquery实现标签支持图文排列带上下箭头按钮的选项卡
Mar 14 Javascript
JS控制HTML元素的显示和隐藏的两种方法
Sep 27 Javascript
Javascript中字符串和数字的操作方法整理
Jan 22 Javascript
JS常用倒计时代码实例总结
Feb 07 Javascript
关于Bootstrap按钮组件消除黄框的方法
May 19 Javascript
最通俗易懂的javascript变量提升详解
Aug 05 Javascript
element-ui表格合并span-method的实现方法
May 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
php自动跳转中英文页面
2008/07/29 PHP
关于初学PHP时的知识积累总结
2013/06/07 PHP
Drupal简体中文语言包安装教程
2014/09/27 PHP
php两种无限分类方法实例
2015/04/21 PHP
PHP实现的mysql操作类【MySQL与MySQLi方式】
2017/10/07 PHP
javascript 读取xml,写入xml 实现代码
2009/07/10 Javascript
鼠标拖动实现DIV排序示例代码
2013/10/14 Javascript
jquery 漂亮的删除确认和提交无刷新删除示例
2013/11/13 Javascript
JS实现带关闭功能的阿里妈妈网站顶部滑出banner工具条代码
2015/09/17 Javascript
jQuery实现单击弹出Div层窗口效果(可关闭可拖动)
2015/09/19 Javascript
原生JS实现简单放大镜效果
2017/02/08 Javascript
iview日期控件,双向绑定日期格式的方法
2018/03/15 Javascript
layer更改皮肤的实现方法
2019/09/11 Javascript
快速解决layui弹窗按enter键不停弹窗的问题
2019/09/18 Javascript
mapboxgl实现带箭头轨迹线的代码
2021/01/04 Javascript
Python在Windows和在Linux下调用动态链接库的教程
2015/08/18 Python
小议Python中自定义函数的可变参数的使用及注意点
2016/06/21 Python
Python实现简单网页图片抓取完整代码实例
2017/12/15 Python
python判断完全平方数的方法
2018/11/13 Python
如何在python中写hive脚本
2019/11/08 Python
python 实现Harris角点检测算法
2020/12/11 Python
HTML5 语义化结构化规范化
2008/10/17 HTML / CSS
英国Boots旗下太阳镜网站:Boots Designer Sunglasses
2018/07/07 全球购物
兰蔻英国官网:Lancome英国
2019/04/30 全球购物
德国帽子专家:Hutshopping
2019/11/03 全球购物
LVMH旗下最大的奢侈品网站平台:24S
2020/05/24 全球购物
随机分配座位,共50个学生,使学号相邻的同学座位不能相邻
2014/01/18 面试题
vue实现倒计时功能
2021/03/24 Vue.js
护士试用期自我鉴定
2014/02/08 职场文书
少儿节目主持串词
2014/04/02 职场文书
五年级学生期末评语
2014/12/26 职场文书
租车协议书
2015/01/27 职场文书
认识实习感想
2015/08/10 职场文书
入党申请书怎么写?
2019/06/21 职场文书
MySQL入门命令之函数-单行函数-流程控制函数
2021/04/05 MySQL
详解SQL的窗口函数
2022/04/21 Oracle