数字签名

数字签名是一种用于签署消息验证消息签名的密码学工具,旨在为数字消息或电子文档提供真实性证明。数字签名可以提供:

  • 消息认证——证明某个已知发送者(私钥所有者)创建并签署了该消息。
  • 消息完整性——证明消息在签名后未被篡改。
  • 不可否认性——签名一旦生成,签名者就无法否认签署过该文档。

如今,数字签名广泛应用于商业和金融行业,例如授权银行付款(资金转账)、交换已签名的电子文档、签署公有区块链系统中的交易(如转移加密货币、代币或其他数字资产)、签署数字合同,以及许多其他场景。

数字签名无法识别创建某个签名的人是谁。这个问题可以结合数字证书来解决;数字证书会将公钥所有者与某个身份(个人、组织、网站或其他主体)绑定。按照设计,数字签名将消息与公钥绑定,而不是与数字身份绑定。

签署消息和验证签名:工作原理

数字签名方案通常采用公钥密码系统(如 RSA 或 ECC)以及公钥/私钥对。消息用私钥签名,并用相应的公钥验证签名:

发送者使用私钥(签名密钥)对消息进行签名。通常先对输入消息进行哈希,再由签名算法计算签名。大多数签名算法会使用消息哈希值和签名密钥进行某种计算,并确保没有签名密钥就无法计算出结果。消息签名的结果是数字签名(一个或多个整数):

signMsg(msg, privKey) 🡒 signature

消息签名由相应的公钥(验证密钥)进行验证。通常先对已签名的消息进行哈希,然后签名算法使用消息哈希值和公钥执行某种计算。验证结果是一个布尔值(签名有效或无效):

verifyMsgSignature(msg, signature, pubKey) 🡒 valid / invalid

消息签名从数学上保证某条消息由某个(保密的)私钥签署,而该私钥对应某个(非保密的)公钥。消息签名后,消息和签名都不能被修改,从而保证消息的认证性完整性。任何知道消息签名者公钥的人都可以验证签名。签名完成后,签名者无法否认签名行为(这称为不可否认性)。

大多数签名方案的工作方式如下图所示:

签名时,会对输入消息进行哈希(单独哈希,或与公钥及其他输入参数一起哈希),然后通过某种计算(基于椭圆曲线、离散对数或其他密码学原语)得出数字签名。生成的已签名消息由原始消息和计算出的签名组成。

签名验证时,会对待验证消息进行哈希(单独哈希或与公钥一起哈希),并基于消息哈希值数字签名公钥执行一些计算,最后通过比较来判断签名是否有效。

数字签名不同于 MAC(消息认证码):MAC 使用对称算法和同一个密钥来创建与验证,而数字签名使用签名密钥创建,并由与签名密钥相对应的另一个验证密钥通过非对称算法进行验证。签名和 MAC 都能提供消息认证与完整性保证。

数字签名方案与算法

大多数公钥密码系统(如 RSAECC)都提供安全的数字签名方案(签名算法)。著名的数字签名方案包括:DSAECDSAEdDSARSA 签名#Signing_messages)、ElGamal 签名Schnorr 签名

上述签名方案的安全性基于 DLP(离散对数问题)和 ECDLP(椭圆曲线离散对数问题)的困难性,因此可被量子计算破解(足够强大的量子计算机可能从消息签名中计算出签名密钥)。与 ECDSA 和 EdDSA 相比,抗量子签名(如 SPHINCSBLISSXMSS)的密钥和签名较长、性能较慢,因此尚未得到大规模应用。

截至 2018 年 11 月,最流行的数字签名方案是:RSA 签名#Signing_messages)、ECDSAEdDSA。下面将结合可运行的代码示例介绍它们的更多细节。

RSA 签名

RSA 公钥密码系统提供了一种密码学安全的数字签名方案(签名和验证),其基础是模幂运算与离散对数的数学原理,以及整数分解问题IFP)的困难性。RSA 签名/验证过程如下:

  • RSA 签名#Signing_messages)算法先计算消息哈希值,再用私钥指数加密该哈希值以获得签名。所得签名是一个整数(经 RSA 加密的消息哈希值)。
  • RSA 验证算法先计算消息哈希值,再用公钥指数解密消息签名,并将得到的已解密哈希值与已签名消息的哈希值比较,以确认签名有效。

RSA 签名是确定性的(相同消息和相同私钥会产生相同签名)。通过在签名前向输入消息填充一些随机字节,很容易设计出非确定性的 RSA 签名变体。

RSA 签名广泛应用于现代密码学,例如签署数字证书以保护网站。截至 2018 年 11 月,微软官方网站的数字证书就使用了 Sha256RSA。不过,过去十年的趋势是从 RSA 和 DSA 转向基于椭圆曲线的签名(如 ECDSA 和 EdDSA)。现代密码学家和开发者更偏爱 ECC 签名,因为其密钥和签名更短、相同密钥长度下的安全性更高,而且性能更好。

DSA(数字签名算法)

DSA(数字签名算法)是一种密码学安全的数字签名标准(用于消息签名和签名验证),其基础是模幂运算与离散对数的数学原理,以及离散对数问题(DLP)的困难性。它是 RSA 的替代方案;由于 RSA 在 2000 年 9 月前受专利限制,DSA 曾被用来取代 RSA。DSAElGamal 签名方案的一种变体。DSA 签名/验证过程如下:

  • DSA 签名算法先计算消息哈希值,再生成随机整数 k 并计算签名(一对整数 {r, s});其中 rk 计算得出,而 s 使用消息哈希值私钥指数和随机数 k 计算得出。由于存在随机性,签名是非确定性的
  • DSA 签名验证算法会基于消息哈希值公钥指数和签名 {r, s} 进行计算。

随机值 k(计算签名时生成)会带来潜在漏洞:如果使用相同的 k 值和相同的私钥签署两条不同的消息,攻击者便可以直接计算出签名者的私钥(参见 https://github.com/tintinweb/ecdsa-private-key-recovery)。

RFC 6979 定义了一种确定性 DSA 变体,它根据私钥、消息哈希值和其他几个参数,通过 HMAC 计算随机数 k。通常认为确定性 DSA 更安全

在现代密码学中,基于椭圆曲线的签名(如 ECDSA 和 EdDSA)比 DSA 更受青睐,因为其密钥和签名更短、相同密钥长度下的安全级别更高,而且性能更好。

ECDSA(椭圆曲线数字签名算法)

ECDSA(椭圆曲线数字签名算法)是一种基于椭圆曲线密码学(ECC)的密码学安全数字签名方案。ECDSA 依赖有限域上椭圆曲线循环群的数学原理,以及 ECDLP 问题(椭圆曲线离散对数问题)的困难性。

ECDSA 是经典 DSA 算法的一种改编,而 DSA 源自 ElGamal 签名方案。更准确地说,ECDSA 算法是 ElGamal 签名的一种变体,并对群元素(椭圆曲线上的点)的表示方式做了若干调整与优化。与其他椭圆曲线密码算法一样,ECDSA 使用椭圆曲线(如 secp256k1)、私钥(曲线密钥长度范围内的随机整数,用于签署消息)和公钥(由私钥乘以曲线生成元点计算出的 EC 点,用于验证签名)。ECDSA 签名/验证过程如下:

  • ECDSA 签名算法先计算消息哈希值,再生成随机整数 k 并计算签名(一对整数 {r, s});其中 rk 计算得出,而 s 使用消息哈希值私钥和随机数 k 计算得出。由于存在随机性,签名是非确定性的
  • ECDSA 签名验证算法会基于消息哈希值公钥签名 {r, s} 进行计算。

随机值 k(计算签名时生成)会带来潜在漏洞:如果使用相同的 k 值和相同的私钥签署两条不同的消息,攻击者便可以直接计算出签名者的私钥(参见 https://github.com/tintinweb/ecdsa-private-key-recovery)。

RFC 6979 定义了一种确定性 ECDSA 变体,它根据私钥、消息哈希值和其他几个参数,通过 HMAC 计算随机数 k。通常认为确定性 ECDSA 更安全

截至 2018 年 11 月,ECDSA 签名是应用最广泛的签名算法,每天有数百万人使用。例如,亚马逊网站的数字证书由 Sha256ECDSA 签名方案签署。

EdDSA(Edwards 曲线数字签名算法)

EdDSA(Edwards 曲线数字签名算法)是一种快速的数字签名算法,使用 Edwards 形式的椭圆曲线(如 Ed25519Ed448-Goldilocks)。它是 Schnorr 签名方案的一种确定性变体,由著名密码学家 Daniel Bernstein 的团队设计。

EdDSAECDSA简单、更安全,而且其设计目标是在密钥长度相当的曲线上比 ECDSA 更快。与 ECDSA 一样,EdDSA 签名方案的安全强度依赖 ECDLP 问题(椭圆曲线离散对数问题)的困难性。

EdDSA 签名算法使用 Curve25519Curve448 等 Edwards 椭圆曲线,这些曲线针对性能安全性进行了高度优化。研究表明,在密钥长度相当的曲线上,Ed25519 签名通常比传统的 ECDSA 签名,但两者的性能优劣仍存在争议。EdDSA 签名/验证过程如下:

  • EdDSA 签名算法会生成一个确定性(而非随机)整数 r(通过对消息私钥的哈希值进行哈希来计算),然后计算签名 {Rs, s};其中 Rsr 计算得出,而 s 则根据(消息、由私钥派生的公钥和数字 r)的哈希值以及私钥计算得出。该签名是确定性的(同一密钥对同一消息签名时,总会得到相同签名)。
  • EdDSA 签名验证算法会执行椭圆曲线计算,其依据是消息(与公钥及签名中的 EC 点 Rs 一起进行哈希)、公钥以及签名 {Rs, s} 中的数字 s

按照设计,EdDSA 签名是确定性的(这提升了其安全性)。通过在签名前向输入消息填充一些随机字节,很容易设计出非确定性的 EdDSA 签名变体。

下面简要比较 Ed25519 EdDSA 签名与 secp256k ECDSA 签名:

EdDSA-Ed25519 ECDSA-secp256k1
性能来源 快 8% 慢 8%
私钥长度 32 字节(256 位 = 251 个可变位 + 5 个预定义位) 32 字节(256 位)
公钥长度(压缩后) 32 字节(256 位 = 255 位 y 坐标 + 1 位 x 坐标) 33 字节(257 位 = 256 位 x 坐标 + 1 位 y 坐标)
签名大小 64 字节(512 位) 64 字节(512 位);包含公钥恢复位时为 65 字节(513 位)
公钥恢复 不可能(签名验证涉及对公钥进行哈希) 可能(在签名中增加 1 个恢复位)
安全级别来源 ~128 位(更精确地说是 125.8) ~128 位(更精确地说是 127.8)
SafeCurves 安全性来源 通过 11/11 项测试 通过 7/11 项测试

现代开发者经常使用 Ed25519 签名代替基于 256 位曲线的 ECDSA 签名,因为 EdDSA-Ed25519 签名方案的密钥可容纳于 32 字节(64 个十六进制数字)中,签名可容纳于 64 字节(128 个十六进制数字)中,签名和验证更快,而且通常被认为安全性更好。

公有区块链(如比特币和以太坊)通常使用基于 secp256k1 的 ECDSA 签名,因为只需在签名中额外增加 1 位,就能从签名(结合已签名消息)轻松恢复签名者的公钥及其区块链地址。

一般认为,EdDSA 签名比 ECDSA 更值得推荐,但这一观点颇具争议,实际选择取决于使用场景、所用曲线及许多其他参数。

其他签名方案与算法

大多数签名算法都源自 ElGamal 签名Schnorr 签名等通用签名方案。

  • RSA 签名源自 RSA 加密方案。
  • DSAECDSA 源自 ElGamal 签名方案。
  • EdDSA 源自 Schnorr 签名方案。

其他签名方案包括:

  • ECGDSA:一种椭圆曲线数字签名方案(基于 ECDLP 问题的困难性),是 ECDSA 的略微简化变体,被称为德国版 ECDSA
  • ECKDSA:一种椭圆曲线数字签名方案(基于 ECDLP 问题的困难性),是 ECDSA 的复杂变体,被称为韩国版 ECDSA。ECKDSA 使用给定的 EC 私钥对指定消息以及签名者的数字证书哈希值进行签名。除消息认证、完整性和不可否认性之外,这还为数字签名增加了身份信息。
  • SM2 签名:一种椭圆曲线数字签名方案(基于 ECDLP 问题的困难性),由中国科学院开发,被称为中国数字签名算法
  • GOST R 34.10-2001:一种椭圆曲线数字签名方案(基于 ECDLP 问题的困难性),被称为俄罗斯数字签名算法,是俄罗斯密码标准算法(称为 GOST 算法)之一。

简要回顾最流行的数字签名算法后,下面将结合代码示例,深入介绍 RSA 签名ECDSAEdDSA 签名算法的技术细节。

results matching ""

    No results matching ""