映月读书网 > 区块链:技术驱动金融 > 1.3 数字签名 >

1.3 数字签名

在本节,我们将讨论数字签名(digital signatures)。数字签名是密码学中的第二个重要部分,该理论和哈希函数一起,为我们后面讨论加密货币奠定基础。数字签名被认为是对纸上手写签名的数字模拟。我们对数字签名有两个特性要求,使其与我们对手写签名的预期一致。第一,只有你可以制作你自己的签名,但任何看到它的人都可以验证其有效性;第二,我们希望签名只与某一特定文件发生联系,因此该签名不能用于表明你同意或支持另一份不同的文件。对于手写签名来说,第二条就如同确保别人不能将你的签名从一份文件上剪下来,贴到另一份文件的末尾那样。

那我们如何通过密码学来构建这些性质呢?首先,让我们把之前的直观讨论说得更具体一些,以便今后可以更好地论证数字签名方案,并讨论其安全特性。

数字签名方案

数字签名方案由以下三个算法构成:

● (sk, pk) :=generateKeys(keysize) generateKeys方法把keysize作为输入,来产生一对公钥和私钥。私钥sk被安全保存,并用来签名一段消息;公钥pk是人人都可以找到的,拿到它,就可以用来验证你的签名。

● sig:=sign(sk, message) 签名过程是把一段消息和私钥作为一个输入,对于消息输出是签名。

● isValid:=verify(pk, message, sig) 验证过程是通过把一段消息和签名消息与公钥作为输入,如果返回的结果是真,证明签名属实;如果返回的结果为假,证明签名消息为假。

我们要求以下两个性质有效:

● 有效签名可以通过验证,即:

verify(pk, message, sign(sk, message))==true

● 签名不可伪造。

我们注意到generateKeys和sign都可以采用随机算法。的确,generateKeys最好是随机的,因为它需要为不同的人生成不同的密钥,而verify则需要是确定的。

现在,让我们更详细地检验我们要求数字签名方案具备的两个特性。第一个特性很直接,那就是有效的签名必须通过验证。如果我用我的密钥sk签署了一条消息,之后有人试图通过使用我的公钥pk验证关于同一条消息的签名,该签名必须证实为正确。这个特性是对签名有效的最基本要求。

不可伪造性。第二个要求计算上不可能伪造签名。也就是说,知道你公钥并看到你在某些信息上签名的对手,不能伪造他还未见过的你在其他信息上的签名。这一不可伪造特性类似于我们与对手之间在进行一场游戏,游戏的使用在密码安全证明中很常见。

在不可伪造性游戏中,对手会声称他可以伪造签名,而挑战者会测试他所说的话(见图1.9)。我们做的第一件事是使用generateKeys方法生成一个密钥,以及相应的公共验证公钥,我们将密钥交给挑战者,然后将公钥交给挑战者以及对手。因此,对手只知道公共信息,而他的任务是试图伪造一条信息。挑战者知道密钥,因此他可以签名。

图1.9 不可伪造性游戏

注:不可伪造性游戏是对手(黑客)和挑战者一起玩这样一个游戏:如果黑客可以在一个之前没有见过的消息上进行签名,那么黑客就赢得这个游戏;反之,如果黑客做不到,挑战者就赢得游戏,从而可以证明这个数字签名方案是不可伪造的。

直观来看,这个游戏的设定与真实世界条件一致,现实中的攻击者很可能可以从潜在受害者的很多不同文件中看到有效签名,攻击者甚至还可能操控受害者签署一份看起来无害但对黑客有利的文件。

为了将这一点建模到我们的游戏中,我们将允许黑客选择一些文件的签名,不限时长,只要猜测的数量合情。合情猜测数量的意思是,我们允许攻击者尝试猜测的次数高达百万,但数量高达280就不行了。从渐进性角度来说,我们允许攻击者多次尝试,尝试次数可以是一个密钥大小的多项式函数,但次数不能更多(例如攻击者不能以指数方式猜测)。

一旦攻击者满意他所看到的签名数量,那他就可以挑选某条信息M,尝试在上面伪造签名。对M的唯一限制就是,它必须为攻击者之前未在之上看过签名的信息(因为很明显,攻击者可以发出他收到过的签名)。挑战者运行验证算法,以此确定攻击者生成的关于M信息签名在经过公共验证密钥验证后,是否属实。如果验证成功,攻击者赢得游戏。

不论对手使用什么算法,我们说签名方案不可伪造,当且仅当他成功伪造信息的机会非常小——小到我们可以假设在实践中从不会发生。

实践中的考量

要将算法概念转化为现实中可执行的数字签名机制,我们还需要考虑许多实际问题。例如,很多签名算法是随机的(特别是比特币使用的算法),因此我们需要随机性的良好来源。我们不能低估这一点的重要性,因为不良随机性会使你认为安全的算法变得不安全。

另一个实际问题是关于信息大小。在实践中,你能够签署的信息大小是有限制的,因为真实的方案将在位数长度有所限制的字符串中运行。有一个简单的方法可以解决这个限制:对信息的哈希值进行签署,而非对信息本身进行签署。如果我们使用输出值为256位的加密的哈希函数,那么我们可以有效地签署任何长度的信息,只要我们的签名方案能够签署256位的信息。如上所述,我们可以将信息的哈希值作为信息摘要,哈希函数具有碰撞阻力,因此这种方式是安全的。

我们后面会用到的另一个技巧是,可以对于哈希指针进行签署。如果你签署了哈希指针,那么该签名覆盖(或者说保护)整个结构——这不仅仅是哈希指针本身,还包括哈希指针指向的整个区块链。比如,如果签署了区块链末尾的哈希指针,其结果就是你有效地数字签署了整条区块链。

椭圆曲线数字签名算法

现在让我们来看一下具体的细节。比特币使用的数字签名方案叫作椭圆曲线数字签名算法(ECDSA)。ECDSA为美国政府的标准,是早前DSA[1]算法利用了椭圆曲线的升级版。这些算法经过了数年的细致密码分析,且被普遍认为是安全的。

更具体地说,比特币使用ECDSA算法,而不是标准椭圆曲线“secp256k1”[预计提供128位安全保障,即打破这个算法的难度与执行2128对称性密钥运算(如破解哈希函数)一样困难]。虽然这个曲线是公开标准,但除比特币以外鲜有使用,其他使用ECDSA的应用(如安全网络浏览时的TLS[2]密钥交换)通常都使用更常见的“secp256k1”曲线。这就是比特币的一个古怪之处,因为在比特币系统早期实施中被中本聪选定(参见原版前言),现在已很难改变。

我们不会详细地讨论ECDSA的原理,因为这涉及一些过于复杂的数学知识,且对于本书的其他内容没有太多帮助。如果你对ECDSA感兴趣,请参见本章末尾延伸阅读部分。虽然我们这么说,但对于了解各种参数也许会很有必要:

个人密钥:256位

公钥(未压缩):512位

公钥(压缩):257位

待签名信息:256位

签名:512位

注意,严格来讲,虽然ECDSA只能签署256位的信息,但这存在问题,因为信息在签署之前总是已经经过哈希压缩,因此,任何大小的信息都能被有效签署。

使用ECDSA时,确保随机性良好来源至关重要,因为不良来源将可能导致密钥信息的泄露。这一点不难理解,如果你使用了不良随机来生成密钥,那么该密钥就可能不安全。但是ECDSA的古怪就在于,即使你仅仅只是在生成签名时使用了不良随机,而你使用的密钥完美无缺,你的个人密钥还是有可能泄露(熟悉DSA的人都知道这是DSA的古怪之处,但并不针对椭圆曲线)。接着游戏就结束了,如果你的个人密钥泄露,对手就可以伪造你的签名。因此,我们在实践中要特别注意使用良好随机来源,使用不良随机来源是安全系统的一个常见缺陷。

数字签名作为密码学基础,我们对其讨论就此结束。在下一节,我们将讨论对打造加密货币会带来帮助的一些数字签名应用。

加密货币及加密术

如果你一直在期待比特币使用的加密算法,我们可能会让你失望了,比特币并没有使用任何加密术,因为并没有加密的需要。加密术只是因为现代密码学而变得可能成为众多技术中的一个,很多技术(如承诺方案)在某种程度上隐藏信息,但是与加密术有所不同。

[1] DSA (Digital Signature Algorithm),电子签名算法。——译者注

[2] TLS(Transport Layer Security),传输层安全协议,用于在两个通信应用程序之间提供保密性和数据完整性。——译者注