详解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 相关文章推荐
Code:loadScript( )加载js的功能函数
Feb 02 Javascript
B/S开发中常用javaScript技术与代码
Mar 09 Javascript
基于jquery实现的鼠标滑过按钮改变背景图片
Jul 15 Javascript
关于锚点跳转及jQuery下相关操作与插件
Oct 01 Javascript
JavaScript从数组的indexOf()深入之Object的Property机制
May 11 Javascript
jQuery购物网页经典制作案例
Aug 19 Javascript
Vuejs实现带样式的单文件组件新方法
May 02 Javascript
js 开发之autocomplete=&quot;off&quot;在chrom中失效的解决办法
Sep 28 Javascript
vue子传父关于.sync与$emit的实现
Nov 05 Javascript
解决新建一个vue项目过程中遇到的问题
Oct 22 Javascript
javascript实现移动端轮播图
Dec 09 Javascript
ReactRouter的实现方法
Jan 25 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安装问题
2006/10/09 PHP
php5中类的学习
2008/03/28 PHP
php简单对象与数组的转换函数代码(php多层数组和对象的转换)
2011/05/18 PHP
基于php伪静态的实现详细介绍
2013/04/28 PHP
基于php下载文件的详解
2013/06/02 PHP
php实现银联商务公众号+服务窗支付的示例代码
2019/10/12 PHP
JavaScript 精粹读书笔记(1,2)
2010/02/07 Javascript
JS图片预加载 JS实现图片预加载应用
2012/12/03 Javascript
总结JavaScript设计模式编程中的享元模式使用
2016/05/21 Javascript
Bootstrap进度条实现代码解析
2017/03/07 Javascript
VUE 实现滚动监听 导航栏置顶的方法
2018/09/11 Javascript
JavaScript React如何修改默认端口号方法详解
2020/07/28 Javascript
[06:13]DOTA2进化论(修改版)
2013/10/08 DOTA
[01:00:13]完美世界DOTA2联赛 LBZS vs Forest 第一场 11.07
2020/11/09 DOTA
Python UnicodeEncodeError: 'gbk' codec can't encode character 解决方法
2015/04/24 Python
python简单实现计算过期时间的方法
2015/06/09 Python
python使用turtle库绘制树
2018/06/25 Python
python多继承(钻石继承)问题和解决方法简单示例
2019/10/21 Python
Python调用.NET库的方法步骤
2019/12/27 Python
Python对称的二叉树多种思路实现方法
2020/02/28 Python
Python super()方法原理详解
2020/03/31 Python
Python使用plt.boxplot() 参数绘制箱线图
2020/06/04 Python
使用Keras 实现查看model weights .h5 文件的内容
2020/06/09 Python
python实现b站直播自动发送弹幕功能
2021/02/20 Python
CSS3弹性盒模型开发笔记(一)
2016/04/26 HTML / CSS
英国骑行、跑步、游泳、铁人三项运动装备专卖店:Wiggle
2016/08/23 全球购物
Stefania Mode英国:奢华设计师和时尚服装
2017/10/23 全球购物
猫咪家具:CatsPlay
2018/11/03 全球购物
The North Face北面荷兰官网:美国著名户外品牌
2019/10/16 全球购物
请解释一下webService? 如何用.net实现webService
2014/06/09 面试题
天网工程实施方案
2014/03/26 职场文书
机械专业应届毕业生自荐书
2014/06/12 职场文书
人力资源职位说明书
2014/07/29 职场文书
党的群众路线教育实践活动学习笔记范文
2014/11/06 职场文书
公务员考察材料范文
2014/12/23 职场文书
Python语言中的数据类型-序列
2022/02/24 Python