『翻译』理解椭圆曲线签名算法如何保护你的数据安全

原文链接:UNDERSTANDING HOW ECDSA PROTECTS YOUR DATA.


每个人可能都或多或少听说过ECDSA。有的人情况稍好,大概知道这是数字签名,但另一些人可能根本不知道我在说些什么。

我曾经试着理解ECDSA是如何工作的,但是很难搞明白,因为大多数网上的参考资料都是不充分的。它们要么太基础——只解释了基础算法,留下了疑问:现实中到底是怎么工作的——要么太超前——完全略过了他们认为你应该知道的基础。所以你会纠结在“这在现实中是怎么工作的?”和“这一步是怎么得来的?”之中。如果你并没有数学或者密码学学位,但是仍然想要理解ECDSA是如何工作的(而不是“卧槽,管他怎么证明的!”),那么你很不幸,因为根本就没有给新手看的资料。

我决定着手研究ECDSA,来使它更易于理解:它是如何保护我们的数据的并且到底有多安全。在做过很多研究并且最终搞明白它之后,我决定写一篇文章来解释ECDSA是如何工作的、算法是什么、数字签名如何验证、为什么这个签名是不可能伪造的。

理解这些并没有那么简单,而我会在假定读者都是小白的情况下尽我所能解释清楚,也希望每个人都能最终理解。

第一步:什么是ECDSA

ECDSA代表“椭圆曲线数字签名算法”,它被用于创建数据(例如文件)的数字签名来允许你在不降低安全性的情况下保证它的真实性。把它想象成现实中的签名,你可以识别出某个人的签名,但是你不可能在他人未知的情况下伪造签名。这之间的区别仅仅是不能伪造的是ECDSA签名而已。

你不应该将用来加密数据的AES(高级加密标准)与ECDSA混淆。ECDSA并不能阻止别人查看或者访问你的数据,它能保证的不过是确定数据没有损坏。

ECDSA中"Curse"(曲线)和"Algorithm"(算法)是需要注意的,因为这表明了ECDSA基本上完全是关于数学的。所以,在文章的开头,有句话一定要讲:孩纸们啊,在学校可别偷懒,听老师的话,学到的东西总有一天会用到的,出来混是要还的!但是这些数学问题简直是复杂难懂,所以我会努力使他们通俗而可理解,让没有基础的小白也能学会,但你应该具备一些基础的数学知识来正确地理解。我会分成两部分来讲,其一是通过一系列高层次的解释来说明它是如何工作的,其次是深挖内部的工作机制来完成整个的理解。需要说明的是,虽然我对ECDSA有一定的理解,但是我并不是这方面的专家(这篇文章已经被某位ECDSA论文作者修订过,并证明了正确性)。

第二步:理解基础

原理很简单,你有一条曲线对应于一个数学方程式,随机选择曲线上的一点作为原点。之后生成一个随机数,作为你的私钥。用这个方程式、原点和这个随机数做一些数学运算,得到在这个曲线上的另一个点,作为公钥。

当你想要对一个文件签名时,你会用到你的私钥(随机数)和这个文件的哈希码(一个唯一的能代表这个文件的数字),通过一个数学运算来得到你的签名。签名本身分为两部分:R和S。要验证你的签名,你只需要公钥(使用私钥在曲线上计算出来的另一个点)然后把它和签名的一部分(S)代入一个运算中,如果签名是正确的,运算的结果是签名的另一部分(R)。简单来说,一个签名由两部分组成,R和S,并且R和S都是私钥生成的,如果一个数学运算使用了公钥和S得到了正确的R,那签名就是有效的。这并不会泄漏私钥,也不可能只通过公钥来生成签名。(公钥和签名都通过私钥生成,并且不可能反推得到私钥。私钥签名不同的文件会得到不同的签名,公钥是公开的,可以通过一个算法来验证签名是否由正确的私钥签署,译者注)

第三步:为什么使用ECDSA?

是的,你现在已经了解了基础。可能还不能理解更多,这些都是复杂难懂的:公钥、私钥,这到底是什么?别担心,我们会很快学习它们,但是在这之前,有必要小小地解释一下我们为什么使用ECDSA,并且用在哪里。

相比于很明显的“我需要签署一份合同/文件”,这里有一个更被普遍接受的说法:比如有一个程序,它不希望自己的数据被用户破坏或修改;比如一个游戏只允许你一个人加载官方地图;再比如阻止修改器、手机或其他设备,而只允许你的设备去安装官方应用。

在这些案例中,那个文件(程序、游戏地图、应用)会使用ECDSA签署得到签名,公钥会被捆绑在程序/游戏/设备里用来验证签名,以确认数据没有被修改。与此同时,私钥被保存在一个安全的地方。你可以用公钥来证明签名,却不可能用它来重建或这伪造新的签名,之后公钥就可以分配给程序/游戏/设备而没有任何后顾之忧。

这与AES(高级加密系统)加密系统不同,后者允许你将数据加密成密码,并且需要key(密钥)来解密,这一类的应用程序需要捆绑密钥,而这与我们的目标相悖。

有一个很好的例子:PS3游戏机被破解,内部的所有文件都被解密,并且所有文件内部的密钥都被提取出来了,但是最后仍有一点需要破解的是ECDSA签名,它可以防止任何人把程序运行在最新的固件上。

第四步:数学基础与二进制

OK,马上要进行更深层次的理解了,我建议你先吃一片止痛药,因为这会很痛!

让我们先从基础开始(这对已经了解的人来说可能很无聊,但是对不知道的人来说是必需的):ECDSA只使用整数数学,没有小数点(这意味着可能的值为1、2、3等,而不是1.5、2.5等),并且,整数的范围取决于签名的位数(bits)(更多的位数意味着更大的整数,也意味着更高的安全性,因为反推出这个整数的难度会更大),像你应该知道的,电脑用“位”(bits)来表示数据,一位就是二进制中的一个数(0或1),而8位代表一个字节(byte)。每次你增加一位,那最大数字就会翻倍,4位可以代表0到15(总共16个)的数;使用5位,可以表示32个值;6位,表示64个值,等等。一个字节(8位)可以表示256个值,而32位可以表示4294967296个值(约40亿)。通常ECDSA会使用160位,那么,,,好吧,这是一个非常非常大的数有49位(十进制,译者注)。

另一个你需要知道的数学概念是余数,可以简单的理解为整除后的剩余部分。比如,x mod 10表示x10除之后的剩余部分,也就是一个0到9的数,所以142 mod 10得2。另一个例子,x mod 2如果等于0那x为偶数,等于1则x为奇数。

第五步:哈希

ECDSA与消息的SHA1加密哈希值一起用于(文件的)签名。哈希指的是另一个数学问题,使用数据的每一个字节得出一个唯一的数字。比如,所有字节的值的和可以作为一个笨一点的哈希函数。所以,如果消息(文件)发生任何改变,哈希值都会完全不同。在SHA1哈希算法中,结果总是20字节(160位)。它对于验证文件没有被修改非常有用,你可以从一个任意大小的文件得到一个20字节的哈希值,然后你可以很容易地再次计算得到哈希值来确认是否匹配。ECDSA实际签名的就是这个哈希值,所以一旦数据改变,哈希值就会改变,哈希值一旦改变,签名就失效了。

我们举个例子来更容易地理解这个问题。我们会使用最简单(最蠢)的哈希函数,在这个函数中,我们对所有数据求和然后对10取余作为结果。

首先,你必须明白,所有数据都会被解释为数字。一个文本文件就是一系列的字节,每一个字节如之前所说代表8位,可以表示0到255之间的整数。所以我们把每一个字节看作是一个整数,把一个文件的每一个字节相加,然后对10取余,最后得到一个0到9之间的数作为哈希值。使用相同的数据总是会得到相同的哈希值,如果改变文件的一个字节,那结果可能会不同。当然,你肯定明白很容易通过改变文件来得到相同的哈希值,因为一共就10种可能性(0到9)。每次改变文件就有十分之一的可能性得到相同的哈希值。

这时需要SHA1登场了。SHA1算法比我们的对10取余的哈希函数要复杂得多得多得多。。。它会给出一个极其大的数(160位,10进制下就是49位)并且有一个特性,就是即使数据的单个字节发生改变,那这个数字也会面目全非。

这使得SHA1成为了一个很优秀的哈希算法。这种算法是不可预测并且非常安全的,几乎不可能发生“碰撞”(两个不同的文件具有相同的哈希值)。在现实中不可能通过伪造数据来获得特定的哈希。

第六步:ECDSA方程

那它是如何工作的?椭圆曲线密码学基于一个方程:

y^2=(x^3+a*x+b) mod p

首先注意到的是模运算(取余)和“Y”是平方的(别忘了这是一个曲线对应的方程)。这意味着对于任意x坐标(注意我们只取整数),都会得到两个y值,也就是说函数图像是沿X轴对称的。模数(也就是P,译者注)是一个质数并且保证了所有值都在160位(二进制)之内(一个数除以p的余数小于p),并且允许使用二次剩余模反元素(倒数)的数学运算来使计算更加简便。因为模运算的存在,y的平方所有可能的值在0到p-1之内,我们有了y^2的所有可能性。又因为我们是在整数上取值,可以进一步缩小范围,y的平方是小于p的完全平方数(整数的平方),这给了我们曲线上N个可能的点且N<p(N为0到p之间的完全平方数的数量),你跟上了吗?:)

(此处存疑,根据下文表述和个人理解,此处的”曲线“指的是y^2关于x的曲线,因为y^2开平方得到两个y值,一正一负,如果是y关于x的曲线的话应该得到2N个点;或者把N理解为0到p之间的完全平方数的数量的2倍。详见原文。译者注)

每一个x值会产生两个点(一正一负,y^2的平方根),这意味着有N / 2个可能的'x'坐标是有效的并且在曲线上给出一个点。因为取整数和模数运算,这导致这个椭圆曲线上有有限个点。(要得到N个点,就需要N/2个x坐标,译者注)

啊,真的难!先来总结一下再继续。ECDSA方程给出了一条拥有有限(N)个有效点的曲线,因为Y轴受模量(p)限制并且需要是沿X轴对称的完全平方数(y^2)。我们有N/2个可能有效的x坐标。最后别忘了N<p。

第七步:点的加法运算


另一个你需要知道的关于椭圆曲线的事是:点加法。它被定义为一个点P加另一个点Q得到第三个点S。具体地,过P和Q做一条直线,与函数曲线相交与第三个点R,这个点与S点的y值相反(记住曲线沿X轴对称)。在这种情况下,我们定义R=-S来代表R沿X轴的对称点。通过图像更容易阐明,见上图。

你可以看到一条曲线y^2=x^3+ax+b(在这里a=-4,b=0),这条曲线沿X轴对称。P+Q的结果是点R沿X轴的对称点,而R是P、Q连线与曲线相交的第三个点。

第八步:点的乘法运算



以同样的方式,如果你做P+P,结果是点R沿X轴的对称点。点R为过点P的切线与曲线的另一个交点。P+P+P的结果是P+P得到的点再与P相加,那P+P+P可以写作(P+P)+P。这将点乘法定义为:k*P即为P与自身相加k次。以上两图为例。

你可以看到两条椭圆曲线,过点P做一条切线与曲线相交与另一个点(原文表述为third point,第三个点,译者注),这个点沿X轴的对称点即为点2P。然后过点2P和点P做一条直线,与曲线相加的点沿X轴对称得到点3P。以此类推。你可能已经在猜测了,为什么加法运算定义需要取X轴对称点。因为如果不这样的话,多个相同的点相加会得到同一条直线,与曲线相加与同一个点。

第九步:陷阱门函数

这样的点乘法有一个特性:一个点R=k*P,不可能通过R和P得到k的值。因为没有点的减法和除法运算,所以无法通过R/P得到k。在图像上,最终的结果是一个点,这可能是数百万次加法的结果,只通过一个结果,不足以知道做了多少次运算,所以无法得到k的值。

即使知道结果点和原点也不可能反推得到被乘数的原理是ECDSA算法安全性的基础,这种原理被称为“陷阱门函数”。

第十步:ECDSA算法

我们已经掌握了“基础”,现在来聊一聊真正的ECDSA签名算法。

对ECDSA来说,你首先需要知道的是你的曲线参数,也就是a、b、p、N和G。a和b是曲线方程(y^2=x^3+ax+b)中的参数,“p”是质数模数,“N”是曲线上点的数量,最后对ECDSA来说还需要一个“G”,它代表一个“参考点”(reference point)或者说一个自定义的原点(origin)。参考点可以是曲线上的任意点。

这些参数很重要,如果没有它们很明显就不可能签署或证实一个签名。Yes,证明一个签名不只是需要公钥,也必须知道推倒出公钥的曲线参数。NIST(美国国家标准技术研究所)和SECG(高效密码学标准组织)提供了安全和高效的曲线参数。

首先,你要有一个私钥和一个公钥,私钥是一个随机数(160位,二进制),公钥是一个使用点G和私钥进行点乘法而得到的曲线上的一个点。我们使用“dA”作为私钥(随机数),“Qa”作为公钥(一个点),所以有:Qa=dA*G(G是给定参数的曲线上的一个参考点)。

第十一步:创建一个签名

那我们该怎么签署一个文件/消息?

首先,你需要知道签名共有40个字节,由两个20字节的值组成,一个为R另一个为S。这一对值(R和S)共同构成了ECDSA签名。以下是创建两个值签署文件的方法:首先,生成一个随机数(20字节),并使用点乘法运算来计算点R=k*G。这个点的x值代表R。由于曲线上的P点可以由它的(x,y)坐标(每个长20字节)表示,签名时只需要x(20字节)的值(y的值可由x带入方程求得,译者注),这个x值就被称为R。现在需要的只有S了。

为了计算S,必须求得消息的SHA1哈希值,也就是一个20字节的值,你可以把它看作是一个巨大的整型数,并把它称为“z”。现在用以下方程来计算S:

S=k^-1(z+dA*R) mod p

需要注意的是k^-1也就是k的模乘逆元,其实就是k的倒数。由于我们处理的是整数,这是不可能的,所以它是一个数字,并且有(k^-1*k) mod p等于1。这里再次提醒,k是一个随机数,用来计算R,z是消息的哈希值用来签名,dA是私钥,R是点k*G的x坐标(G是特定参数下曲线上一个原点“the point of origin”)。

第十二步:验证签名

现在你已经有了签名,想要验证它很简单,只需要公钥(当然也需要椭圆曲线的参数)。使用以下方程计算得到一个点P:

P=S^-1*z*G+S^-1*R*Qa

如果点P的x坐标等于R,这就意味着签名是有效的,反之无效。

很简单,对吧?现在来看看why和how,这需要一些数学证明:

我们有:P=S^-1*z*G+S^-1*R*Qa

且Qa=dA*G,所以

P=S^-1*z*G+S^-1*R*dA*G=S^-1(z+dA*R)*G

P的x坐标与R匹配,R也是点k*G的x坐标(P就是点k*G),有:

k*G=S^-1(z+dA*R)*G

两边消去G化简为:

k=S^-1(z+dA*R)

交换k与S的位置:

S=k^-1(z+dA*R)

即得到计算签名的方程式。这就是上面第一个等式可以验证签名的原因。

第十三步:ECDSA的安全性


我们讨论一下为什么索尼在PS3上使用的ECDSA算法是错误的,并且黑客是如何获得PS3的ECDSA私钥的。

计算签名需要的方程式:R=k*G,S=k^-1(z+dA*R) mod p,其中有两个未知数(k和dA),无法确定其中的任何一个。

然而,这个算法的安全性基于其具体实现,保证k是随机生成的并且任何人都不可能用任何方法得到k的值是极其重要的。但是索尼犯了一个巨大的错误在算法实现上,他们在所有地方都使用了相同的”k“,这就意味着如果你有两个由相同k生成的签名,那这两个签名就有相同的R值;这就意味着你可以通过两个文件的哈希值z和z',两个S签名S和S'来计算得到k:

S-S'=k^-1(z+dA*R)-k^-1(z'+dA*R)=k^-1(z+dA*R-z'-dA*R)=k^-1(z-z')

所以:k=(z-z')/(S-S')

一旦得到k的值,那关于S的方程就只有一个未知数,很容易解得dA:

dA=(S*k-z)/R

一旦得到私钥dA的值,那你就可以签署你自己的文件,并且PS3会把它认作是正确的由索尼签署的文件。这就是确保随机数是”密码学随机“的重要性。这也是不可能拥有高于3.56版本的自定义固件的原因,因为3.56版本之后索尼修复了ECDSA算法实现并使用了现在的无法找到私钥的新密钥。

还有另一个关于安全性的例子:一些比特币客户端使用了非密码学随机的随机数生成器,这意味着他们的交易使用了相同的k值,这就导致了一些别有用心的人能够找到比特币钱包的私钥并把资金偷走。

有一个经典的笑话来说明这个问题:xkcd comic 221(见上图)。每当这种安全问题发生时人们就会把它搬出来。

ECDSA算法本身是非常安全的并且不可能反推得到私钥——前提是算法被正确实现。如果有一种方法能找到私钥,那每一台电脑每一个网站每一个系统的安全性都会受影响,因为很多系统都是依靠ECDSA来保证安全性的,并且不可能被攻破。

第十五步:结论

终于要结束了!我希望把整个算法都解释清了,虽然我知道确实是很复杂并且难以理解。我经常试着让一些事更易于去理解即使是对于小白来说,但是这个算法太复杂而无法用更简单的术语来解释。

但是如果你是一个开发者或者数学专业人士或者是想要获取帮助或只是简单地想学点知识而对它感兴趣的人,那我相信这包含足够的信息来让你入门或者至少理解这头被称为”ECDSA“的怪兽的背后的概念。

说到这里,我想感谢那些帮助我理解这一切的人,尤其是那些匿名的,以及我在文章中链接到了一些维基百科的页面,和Avi Kak,感谢他的论文解释了ECDSA背后的数学问题,文中的图表图像也出自这篇论文。

Ps:文章中我使用了”160位“来解释ECDSA签名,这是因为SHA1哈希算法得到的值也是160位(20字节)二者相匹配,并且这也是PS3所采用的。但是算法本身可以用任意长度的数。文章中可能还有其他误差,但就像我说的,我并不是一个专家,而且文章的目的是在保证算法完整的情况下尽最大所能降低难度。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值