跳转至

数字签名算法

数字签名方案

  • 公钥签名方案:
    • 利用私钥生成签名
    • 利用公钥验证签名
  • 只有私钥的拥有者才能生成签名,所以能够用于证明谁生成的消息
  • 任何知道公钥的人可以验证消息(他们要确认公钥拥有者的身份,这是公钥的密钥分配问题)
  • 通常不对整个消息签名,因为这将会使交换信息长度增加一倍
    • 使用消息的 hash 值
  • 数字签名可以 提供消息的不可否认性

RSA 签名方案

  • RSA 加密解密是可交换的
  • 可以用于数字签名方案

RSA 密钥生成

  • 选择两个大素数 \(p\)\(q\)
  • 计算 \(n = p \cdot q\)
  • 计算 \(\phi(n) = (p - 1)(q - 1)\)
  • 选择公钥指数 \(e\),满足 \(1 < e < \phi(n)\)\(\gcd(e, \phi(n)) = 1\)
  • 计算私钥指数 \(d\),满足 \(d \cdot e \equiv 1 \bmod \phi(n)\)
  • 公钥是 \((e, n)\)
  • 私钥是 \((d, p, q)\)

RSA 签名生成与验证

  • 给定 RSA 方案 \(\{K=(e, n), K^{-1}=(d, p, q)\}\)

    • 要签名消息 \(M\):计算:

      \[ \begin{cases} h = H(M) \\ S = h^{d} (\bmod n) \\ \end{cases} \Rightarrow (M, S) \]
    • 要验证签名, 计算:

      \[ \begin{cases} h = H(M) \\ h' = S^{e}(\bmod n) \\ \end{cases} \Rightarrow h^{\prime} = h? \]

RSA 签名方案的使用

  • 使用 RSA 加密、认证:
    • 假设 A 发送消息给 B
      • 用发送者的私钥签名:\(S = M^{d_A} \bmod n_A\)
      • 用接收者的公钥加密:\(C = S^{e_B} \bmod n_B\)
    • 接收者 B 解密:
      • \(S = C^{d_B} \bmod n_B\)
      • 验证签名:\(M = S^{e_A} \bmod n_A\)
  • 看起来,一个消息可用 RSA 先加密再签名而不改变大小
    • 但是,加密使用的是消息接收者的模,签名是消息发送者的模,后者可能比前者小
    • 如果先加密再签名,可能会导致加密后的消息大于签名模,无法使用 RSA 进行签名(RSA 要求 \(0 < M < n\)
    • 交换两者顺序,先签名再加密可以避免这个问题
  • 签名常使用 HASH 函数值
    • \(h=H(M)\) 代替消息 \(M\) 进行签名

ElGamal 签名方案

  • ElGamal 加密算法是不可交换的
  • 存在一个相关的签名算法
  • 安全性是 基于计算离散对数的困难性

ElGamal 密钥生成

  • 选择共享的素数 \(p\) 和公开的生成元 \(g\)
  • 每个用户选择一个随机数作为私钥 \(x\)
  • 计算各自的公开密钥:\(y = g^x \bmod p\)
  • 公钥是 \((y, g, p)\)
  • 私钥是 \((x)\)

ElGamal 签名生成与验证

  • 签名消息 \(M\)
    • 选择随机数 \(k\),满足 \(\gcd(k, p - 1) = 1\)
      • \(k\) 应该被销毁或保密,不能重复使用
    • 计算 \(K = g^{k} \bmod p\)
    • 用 Euclidean (inverse) 扩展算法求 \(S\)
      • \(M = x \cdot K + k \cdot S \bmod (p - 1)\) ;
      • 即求 \(S = k^{-1}(M - x \cdot K) \bmod (p - 1)\)
    • 发送 \((M, K, S)\),其中 \((K, S)\) 是对 \(M\) 的签名
  • 验证 \((K, S)\) 是对 \(M\) 的签名:
    • \(y^{K} \cdot K^{S} \equiv g^{M} \bmod p\)
  • 同 ElGamal 加密方案,签名信息也是消息的 2 倍
    • 通常对消息的 HASH 值进行签名

ElGamal 签名方案举例

  • 密钥生成:
    • \(p = 11, g = 2\)
    • 选择私钥 \((x = 8)\)
    • 计算公钥:
      • \(y = g^x \bmod p = 2^8 \bmod 11 = 3\)
      • 公钥是 \((y = 3, g = 2, p = 11)\)
  • \(M = 5\) 签名:

    • 选择随机数 \(k = 9\)
    • 确定 \(\gcd(9, 10) = 1\)
    • 计算:\(K = g^{k} \bmod p = 2^9 \bmod 11 = 6\)
    • 求解:

      \[ 5 = 8 \times 6 + 9 \cdot S \bmod 10; \]
      • 因为 \(9^{-1} \equiv 9 \bmod 10\)
      • 所以 \(S = k^{-1}(M - x \cdot K) \bmod (p - 1) = 9 \times (5 - 8 \times 6) \bmod 10 = 3\)
        • 签名是 \((K = 6, S = 3)\)
      • 要验证签名,确认:
    \[ \begin{aligned} &y^{K} \cdot K^{S} \bmod p = 3 ^ {6} \cdot 6 ^ {3} \bmod 11 = 10 \\ &g^{M} \bmod p = 2 ^ {5} \bmod 11 = 10 \\ \end{aligned} \]

DSA (Digital Signature Algorithm)

  • DSA 是数字签名算法,DSS 是数字签名标准
  • DSA 是 ElGamal 及 Schnorr algorithms 的变形
  • 生成 320 bit 签名
  • 安全性是 基于计算离散对数的困难性
  • 被广泛接受

DSA 密钥生成

  • 首先选取公开参数 \((p, q, g)\)
    • 选取大素数 \(p\)
      • 512 ~ 1024 bit(64 倍数)
    • 选取素数 \(q\)
      • 160 bit
      • \(q\)\(p - 1\) 的因子
    • 选择 \(g = h^{(p - 1) / q}\)
      • 满足对任何 \(h < p - 1, h^{(p - 1) / q} (\bmod p) > 1\)
  • 每个用户选取私钥并计算他们的公钥:
    • 选取 \(x < q\)
    • 计算 \(y = g^{x} \bmod p\)
    • 公钥是 \((y, p, q, g)\)
    • 私钥是 \((x)\)

DSA 签名生成与验证

  • 签名消息 \(M\)

    • 生成随机签名密钥 \(k\),满足 \(k < q\)
    • 计算

      \[ \begin{aligned} &K = (g^{k} \bmod p) \bmod q \\ &S = k^{-1} \cdot (\mathrm{HASH}(M) + x \cdot K) \pmod{q} \end{aligned} \]
  • 发送签名 \((K, S)\) 及消息 \(M\)

  • 验证签名, 计算:

    \[ \begin{cases} w = S^{-1} \pmod{q} \\ u1 = (\mathrm{HASH}(M)\cdot w) \pmod{q} \\ u2 = K\cdot w \pmod{q} \\ v = g^{u1}\cdot y^{u2} \pmod{p}\pmod{q} \\ \end{cases}\quad \Rightarrow v = K? \]

DSA 安全性

  • 基于离散对数
  • 最初建议使用一个共同的 modulus p
  • 现在建议不同的工作组使用不同的 \((p, q, g)\)
  • Gus Simmons 发现存在潜信道,能够泄露私钥

带密钥的 HASH

  • 以上的签名方法都是公钥技术
    • 计算与数据量较大
  • 需要私钥的认证方案

    • 好的方法是使用快速的 hash 函数:
    • 密钥与消息同时参加运算:

      \[ KeyedHash = \mathbf{Hash}(Key \parallel Message) \]
    • 存在一些弱点

    • 随后建议:
    \[ KeyedHash = \mathbf{Hash} (Key_1 \parallel \mathbf{Hash} (Key_2 \parallel Message)) \]

HMAC

  • HMAC 是使用带密钥的 HASH 函数的结果
  • 成为 internet 标准(RFC2104)
  • 结构:

    \[ HMAC_K = \mathbf{Hash}((K^+ \oplus opad) \parallel \mathbf{Hash}((K^+ \oplus \text{ipad}) \parallel M)) \]
    • \(K^+\):经过填充的密钥
    • \(opad, ipad\):特殊的填充值
      • \(opad=01011010\) 重复 \(b/8\)
      • \(ipad=00110110\) 重复 \(b/8\)
    • 安全性是基于原来的 HASH 函数的安全性
    • 任何 MD5, SHA-1, RIPEMD-160 都可以这样使用