好记性不如烂笔头,写一篇文章详细记录一下DSA,ECDSA和EdDSA。
DSA
数字签名算法(DSA)是用于数字签名的联邦信息处理标准之一,基于模算数和离散对数的复杂度。DSA是Schnorr和ElGamal签名方案的变体。1
概述
DSA算法工作在框架公钥加密、模算数和离散对数问题,这被认为是难解问题。该算法使用由公钥和私钥组成的密钥对。私钥用于生成消息的数字签名,并且可以通过使用签名者的相应公钥来验证这种签名。数字签名提供信息鉴定(接收者可以验证消息的来源),完整性(接收方可以验证消息自签名以来未被修改)和不可否认性(发送方不能错误地声称它们没有签署消息)
算法
DSA 算法包含了四种操作:密钥生成、密钥分发、签名、验证
密钥生成
- 选择经核可的 密码散列函数 $H$,在原版的 DSS(Digital Signature Standard)中,$H$ 总是使用 SHA-1,而目前的 DSS 已核可更为安全的 SHA-2 作为散列函数。 假如长度 ${\displaystyle |H|}$ 大于模数长度$N$,则散列函数的输出只有最左边的 $N$ 比特会被使用。
- 选择密钥长度 $L$,原版的 DSS 限制 $L$ 必须为 512 到 1024 之间 64 的倍数,NIST 800-57 建议使用长度为 2048 的密钥。
- 选择模数长度 $N$ 使得 ${\displaystyle N<L}$ 且 ${\displaystyle N\leq |H|}$,FIPS 186-4 规定 ${\displaystyle (L,N)}$ 必须为 (1024, 160)、(2048, 224)、(2048, 256) 或 (3072, 256) 其中一种。
- 选择长度为 $N$ 比特的质数 $q$。
- 选择长度为 $L$ 比特的质数 $p$ 使得 $
{\displaystyle p-1}$ 为 $q$ 的倍数。 - 从 ${\displaystyle \{2\ldots p-2\}}$ 随机选择 $h$。计算 ${\displaystyle g:=h^{(p-1)/q}\mod p}$,当 $g=1$ 时需要重新产生不同的 $h$,通常会使用 ${\displaystyle h=2}$,即使数值很大时仍然可以非常有效率的计算这个模幂。
算法参数为 $(p,q,g)$,可被不同的用户共享。
用户密钥
给定一套算法参数后,第二阶段会为每位用户计算独立密钥组合:
- 从 ${\displaystyle \{1\ldots q-1\}}$ 选择随机整数 $x$
- 计算 ${\displaystyle y:=g^{x}\mod p}$
其中
$x$ 是私钥、
$y$ 是公钥。
密钥分发
签名者需要透过可信任的管道发布公钥
$y$,并且安全地保护
$x$ 不被其他人知道。
签名
消息 $m$ 签名流程如下:
- 从 ${\displaystyle \{1\ldots q-1\}}$ 选择随机整数 $k$
- 计算 ${\displaystyle r:=\left(g^{k}{\bmod {\,}}p\right){\bmod {\,}}q}$,当出现 $r=0$ 状况时重新选择随机数 $k$
- 计算 ${\displaystyle s:=\left(k^{-1}\left(H(m)+xr\right)\right){\bmod {\,}}q}$,当出现$s=0$ 状况时重新选择随机数 $k$.
签名为 ${\displaystyle (r,s)}$ 组合
验证签名
以下步骤可以验证 $
{\displaystyle \left(r,s\right)}$ 是消息
$m$ 的有效签名:
- 验证$0 < r < q, 0 < s < q$
- 计算$w:=s^{-1} \mod q$
- 计算$u_1:=H(m)\cdot w \mod q$
- 计算$u_2:=r\cdot w \mod q$
- 计算$v:=(g^{u_1}y^{u_2}\mod p)\mod q$
只有$v = r$时,签名有效
Correctness
因为所以
所以有
代码实现
1 | from Crypto.Util.number import getPrime, getRandomRange, getRandomNBitInteger, isPrime |
Attack
Attack on DSA with signatures made with k, k+1
随便找了一个attack练练手,后面遇到了新的再补充
根据
我们可以得到
消去$k_1$
我们可以得到
从而
代码实现
1 | def attack_1(): |
ECDSA
其实 ECDSA和DSA差不多,无非就是从素域转移到椭圆曲线上,废话不多说,开干
概述
椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线密码(ECC)对数字签名算法(DSA)的模拟。ECDSA于1999年成为ANSI标准,并于2000年成为IEEE和NIST标准。它在1998年既已为ISO所接受,并且包含它的其他一些标准亦在ISO的考虑之中。与普通的离散对数问题(discrete logarithm problem DLP)和大数分解问题(integer factorization problem IFP)不同,椭圆曲线离散对数问题(elliptic curve discrete logarithm problem ECDLP)没有亚指数时间的解决方法。因此椭圆曲线密码的单位比特强度要高于其他公钥体制。
算法
和DSA一样,ECDSA算法包含了四种操作:密钥生成、密钥分发、签名、验证
写着写着,突然发现自己好像对于椭圆曲线没有做过系统的了解,先挖个坑,回头写一篇博客介绍一下。
密钥生成
只要Alice和Bob选定一个合适的曲线Curve和基点$G$,不过有一点要求,$G$的阶$n$必须是一个素数
Indeed, we assume that every nonzero element of the ring
$\mathbb {Z} /n\mathbb {Z}$ is invertible, so that $\mathbb {Z} /n\mathbb {Z}$ must be a field. It implies that $n$ must be prime
Alice 从 ${\displaystyle \{1\ldots n-1\}}$ 选择随机整数 $d_A$, 作为私钥;计算$Q_A = d_A \times G$作为公钥。
密钥分发
签名者需要透过可信任的管道发布公钥
$Q_A$,并且安全地保护
$d_A$ 不被其他人知道。
签名
- 计算 $e = \text{HASH}(m)$,$\text{HASH}$ 是一个密码哈希函数。
- 取 $z$ 为 e 最左边$|n|$比特,$|n|$ 为 $n$ 的比特长度。注意 $z$ 可以比 $n$ 大,但是不能比 $n$ 长。
- 从 ${\displaystyle \{1\ldots n-1\}}$ 选择随机整数 $k$
- 计算椭圆曲线上点 $(x_1,y_1)= k\times G$
- 计算 $r = x_1 \mod n$,如果 $r=0$,回到step 3
- 计算 $s = k^{-1}(z + rd_A )$,如果 $s=0$,回到step 3
签名为 ${\displaystyle (r,s)}$ 组合,注意${\displaystyle (r,-s)}$也是有效的签名。
验证签名
- 首先检验公钥$Q_A$的有效性:a. 是否为$O$点; b. 是否位于曲线上; c. $n\times Q_A$是否为$O$点。
- 验证$r,s\in [1,n-1]$
- 计算 $e = \text{HASH}(m)$,$\text{HASH}$ 是一个密码哈希函数。
- 取 $z$ 为 e 最左边$|n|$比特,$|n|$ 为 $n$ 的比特长度。
- 计算$u_1 = zs^{-1}\mod n, \,u_2=rs^{-1}\mod n$
- 计算椭圆曲线上点 $(x_1,y_1)=u_1\times G+u_2\times Q_A \mod n$,如果 $(x_1,y_1)=O$,签名无效。
- 如果$r\equiv x_1 \mod n$,签名有效。
Correctness
公钥恢复
- 计算$R=(x_1,y_1)$,$x_1$ 是 $r,r+n,r+2n\dots$中的其中一个。
- 计算$u_1 = -zr^{-1}\mod n, \,u_2=sr^{-1}\mod n$
- 计算$Q_A = (x_A,y_A) = u_1G+u_2R $.
$Q_A$即为公钥
Correctness
代码实现
1 | from Crypto.Util.number import * |
Attack
Attack on ECDSA with signatures made with same k
根据
我们可以得到
从而有
从而可以得到
代码实现
1 | def attack_1(): |
EdDSA
EdDSA给我一种很奇怪的感觉,先留一个坑,等我摸索摸索再填