数字签名之ElGamal签名体制
数字签名原理
一个完整的数字签名方案由三部分组成:密钥生成算法、签名算法和验证算法。密钥生成算法是根据系统参数为签名者生成公钥和私钥;签名算法是产生数字签名的某种算法,而验证算法是检验一个数字签名是否有效(即是否由指定实体生成)的某种算法。如无特殊说明,下文继续用 A 代表签名者,B 代表验证者。
下面给出数字签名的形式化定义:
(1)密钥生成算法
系统初始化产生签名方案的基本参数(M,S,K,Sign,Ver),其中 M 为消息空间,S 为签名空间,K 为密钥空间,包含私钥和公钥,Sign 为签名算法集合,Ver 为签名验证算法集合。用户 A 执行密钥生成算法生成自己的公私密钥$(k_1,k_2)$。
(2)签名算法
对任意的消息 $m \in M$,有$s=sign_{k_2}(m)$,且$s \in S$,那么 s 为消息的签名,将签名消息组(m,s)发送给签名验证者。
(3)验证算法
对于上述的$k_1 \in K$,有相应的签名验证算法:$ver_{k_1}:M \times S \rightarrow \lbrace True,False \rbrace,ver_{k_1} \in Ver$,且
$$
ver_{k1}(m, s) =
\begin{cases}
True & 当 s = sign_{k_2} \newline
False & 当s \neq sign_{k_2}
\end{cases}
$$
签名验证者收到(m,s)后,计算 $ver_{k_1}(m,s)$,若 $ver_{k_1}(m,s)=True$,则签名有效;否则签名无效。
对于每一个$k \in K$,签名函数$ sign*{k_2}$,和签名验证函数 $ver*{k1}$, 是容易计算的。而验证函数 $ver{k1}$是公开的,同时还要求对任意的消息 m,在未知$k_2$条件下从集合 S 中选取 s 使得 $ver{k_1}(m,s)=True$ 是非常困难的,也就是说,攻击者对消息 m 产生有效的签名 s 是不可能的。
根据定义,在进行私钥签名前,先进行消息关键信息提取。
如图 8-1 所示,发送方 A 将消息用 Hash 算法产生一个消息摘要(Message Digest),这个消息摘要有两个重要特性:抗碰撞性和摘要长度固定,使得任何消息产生的签名值长度是一样的。发送方 A 产生消息摘要后,用自己的私钥对摘要进行加密,这个加密后的消息摘要就是数字签名,随后发送方 A 将消息与签名发给接收方 B。B 接收到消息及其签名后,用发送方 A 的公钥解密这个签名,获得由发送方 A 生成的消息摘要,接着用发送方 A 所用 Hash 算法重新生成所获得消息的摘要,然后比对这两个摘要。如果相同,说明这个签名是发送方 A 针对这个消息的有效签名;如果不相同,则签名无效。
依据上述数字签名的基本原理,人们设计出了众多不同种类的数字签名方案,下面将介绍常用数字签名的实现方案。
ElGamal 签名体制
T. EIGamal 于 1985 年提出了一个基于有限域离散对数问题的数字签名方案,美国 NIST 确立的数字签名标准(Digital Signature Standard,DSS)即是在它基础上修订的。EIGamal 数字签名方案是一种非确定性的签名方案,即对给定的一个消息,由于选择的随机数不同而产生不同的数字签名,并且验证算法均会判断为有效。下面简要介绍其方案的实现过程。
-
密钥生成算法
选择一个满足安全性要求的大素数 p,然后选择一个生成元 $g \in Z^_p$;和随机数$x \in _RZ^_p$,,计算$y \equiv g^x(mod\ p)$。则签名者 A 的公钥为(p,g,y),私钥为 x。
-
签名算法
设待签消息为 m,签名者选择随机数$k \in _RZ^*_p$;,计算:$$
\begin{aligned}
&r \equiv g^k(mod \ p) \newline
&s \equiv [h(m)-xr]k^{-1}(mod \ (p-1))
\end{aligned}
$$则对消息 m 的数字签名为(r,s),其中 h 为安全的 Hash 函数
-
验证算法
签名接收者 B 收到消息 m 和签名(r,s)后,首先计算 h(m),然后验证下列等式是否成立
$$
y^rr^s \equiv g^{h(m)}(mod \ p)
$$如等式成立,则签名有效;否则,签名无效。
-
正确性
如果所有算法按步骤执行,则接收者输出签名有效,因为
$$
r \equiv g^k(mod \ p), s \equiv [h(m) - xr]k ^{-1}(mod \ (p - 1))
$$所以
$$
\begin{aligned}
& ks \equiv h(m) - xr(mod \ (p - 1)) \newline
& g^{ks} \equiv g^{h(m) - xr}(mod \ p) \newline
& g^{ks}g^{xr} \equiv g^{h(m)}(mod \ p) \newline
& y^rr^s \equiv g^{h(m)}(mod \ p)
\end{aligned}
$$
案例
-
密钥生成算法
假设 A 选取素数 p=19,$Z^*_p$的生成元 g=2。选取私钥 x=15,计算:
$$
y=g^x \ mod \ p=2^{15} \ mod \ 19 = 12
$$则 A 的公钥是(p=19,g=2,y=12)。
-
签名算法
设消息 m 的 Hash 值 h(m)=16,则 A 选取随机数 k = 11,计算:$$
\begin{aligned}
&r=g^k \ mod \ p \equiv 2^{11} \ mod \ 19=15\newline
&k^{-1} \ mod \ (p-1) = 5
\end{aligned}
$$最后计算签名
$$
s=[h(m)-xr]k^{-1} \ mod \ (p-1)=5(16-15 \times 15) \ mod \ 18=17
$$A 对 m 的签名为(15,17)。
-
验证算法
接收者 B 得到签名(15,17)后计算:
$$
\begin{aligned}
y^rr^s \ mod \ p=12^{15}15^{17} \ mod \ 19=5\newline
g^{h(m)} \ mod \ p \equiv 216 \ mod \ 19=5
\end{aligned}
$$验证等式
$$
y^rr^s \equiv g^{h(m)}(mod \ p)
$$成立,因此 B 接受签名。
注意,本例旨在说明该方案的实现过程,为计算方便所选参数均较为简单。按目前计算能力,通常使用 1024 比特或更大的模数。
C++代码
在写代码的时候我并没有学习优先于离散对数问题~~(懒)~~,因此,关于生成元 g 的知识我并不清楚,我是直接 copy 的生成元函数,但是我会适当的加上我的理解的注释
1 |
|
结果
1 | ElGamal签名验证开始O(∩_∩)O |
安全性
使用 EIGamal 数字签名方案应注意以下安全问题:
-
随机数 k 值的选取和保管
首先,k 值不能泄露。如果 k 值泄露,则容易计算$ x=[ h(m)-sk]r^{-1} \ mod \ (p-1$),签名者
的私钥泄露。其次,随机数 k 不能重复使用。假设 k 用来对两个不同的消息签名,则 r 相同,即$(r,s_1)是m_1$的签名,$(r,s_2)是m_2$的签名。因为
$$
\begin{aligned}
s_1 \equiv [h(m_1)-xr]k^{-1} \ (mod \ (p-1))\newline
s_2 \equiv [ h(m_2)-xr]k^{-1} \ (mod \ (p-1))
\end{aligned}
$$那么有
$$
(s_1-s_2)k \equiv [ h(m_1)-h(m_2)](mod \ (p-1))。
$$又因为消息$m_1和m_2$不同,则$s_1-s_2 \neq 0 \ mod \ (p-1)$的概率很大,则
$$
k \equiv h(m_1)-h(m_2)^{-1}(mod \ (p-1))
$$进而容易计算签名者的私钥 x。
最后,签名者多次签名时所选取多个 k 之间无关联。例如,三个不同的签名所选取的随机数为$ k_1、k_2、k_3$,满足条件$k_3= k_1+k_2$,显然有$r_3= r_1 r_2$,则:由$s \equiv [h(m)-xr]k^{-1} \ (mod \ (p-1))$可得$h(m) \equiv (ks+xr)(mod \ (p-1))$
因此有:
$$
\begin{aligned}
h(m_1)=(xr_1+ k_1s_1)(mod \ (p-1)) \newline
h(m_2)=(xr_2+ k_2s_2)(mod \ (p-1)) \newline
h(m_3)=(xr_3+ k_3s_3)(mod \ (p-1))
\end{aligned}
$$对以上三式分别乘以$s_2s_3,s_1s_3,s_1s_2
$ 得:$$
\begin{align}
h(m_1)s_2s_3=(xr_1s_2s_3+ k_1s_1s_2s_3)(mod \ (p-1)) \newline
h(m_2)s_1s_3=(xr_2s_1s_3+ k_2s_1s_2s_3)(mod \ (p-1)) \newline
h(m_3)s_1s_2=(xr_3s_1s_2+ k_3s_1s_2s_3)(mod \ (p-1))
\end{align}
$$计算式(1)+式(2)-式(3)得
$$
x\equivh(m_1)s_2s_3+ h(m_2)s_1s_3- h(m_3)s_1s_2^{-1}(mod \ (p-1))
$$就可以从中推出签名者的私钥 x。
由此可见,随机数 k 的选取和保管对私钥 x 的保密性起着重要的作用。此外,随机数的使用也保证了签名方案的不可重用性,这是因为在不同时刻选取的随机数不同,即使对同一消息进行签名,也会产生不同的结果,因而避免了 RSA 签名出现的签名重用问题。 -
Hash 函数的应用
如果未使用 Hash 函数则签名方案容易受到攻击。例如攻击者可以选取任一整数对(u,v),满足 gcd(u,p-1)=1。计算$r=g^uy^v \ (mod \ p),s \equiv -rv^{-1}(mod \ (p-1))和m \equiv su(mod \ p)$,则消息 m 及其签名(r,s)可以被验证者接受,即攻击者成功进行存在性伪造。这是因为
$$
y^rr^s \equiv y^r(g^ug^v)^s \equiv y^{r + sv}·g^{us} \equiv y^{r+(-rv^{-1})}·g^{su} \equiv g^m(mod \ p)
$$
又因为$g^m \equiv g^{su}(mod \ p)$也就是说,签名(r,s)使等式$y^rr^s \equiv g^m(mod \ p)$成立。可见,使用 Hash 函数能够有效地提高 EIGamal 数字签名方案的安全性。