Digital Signature Algorithm

**Digital Signature Algorithm**（デジタル シグネチャー アルゴリズム、**DSA**）は、デジタル署名のための連邦情報処理標準である。1991年8月にアメリカ国立標準技術研究所 (NIST) によって**Digital Signature Standard** (**DSS**) での利用を目的として提唱され、1993年にFIPS 186として標準化された。2013年までに4度の改訂を経ている（1996年：FIPS 186-1、2000年：FIPS 186-2、2009年：FIPS 186-3、2013年：FIPS 186-4）。FIPS 186-5では、DSAは新たにデジタル署名を行うことには推奨されないが、標準策定以前に行われた署名の検証には引き続き利用可能とされる。DSAはElGamal署名の改良版の一つであり、それと同様に離散対数問題の困難性に基づく電子署名方式である。

DSAは、かつてNSAに勤めていたDavid W. Kravitzによる1991年7月26日の特許（）によってカバーされている。この特許は「ワシントンD.C.に所在する、商務長官に代表されるアメリカ合衆国」に提供され、NISTが全世界にロイヤリティフリーで開放した。Claus P. Schnorrは、DSAは彼の特許（、失効済み）によってカバーされていると主張したが、この主張に対しては異議が唱えられている。

## 鍵生成
鍵生成は2つのフェイズに分けられる。1つ目は他者と共有されるパラメータの選択であり、2つ目は公開鍵および秘密鍵の生成である。

### パラメータ生成
* 適切な暗号学的ハッシュ関数 *H* を選択する。当初のDSSでは *H* はSHA-1であったが、FIPS 186-4ではSHA-2も選択可能となった。ハッシュの出力値は鍵ペアのサイズに切り詰められる。
* 鍵長 *L* および *N* を決定する。これらが主に暗号強度に影響する。当初のDSSでは、*L* は512から1024の間の64の倍数であった。NIST 800-57においては、*L* を2048あるいは3072とすることで、2010年あるいは2030年まで安全が保たれると推奨された。FIPS 186-3では、*L* と *N* の組み合わせは (1024, 160)、(2048, 224)、(2048, 256)、(3072, 256) の4つと規定された。
* *N* ビットの素数 *q* を選択する。*N* はハッシュの出力長以下でなければならない。
* *p*–1 が *q* の倍数となるような *L* ビットの素数法 *p* を選択する。
* 1 &lt; *h* &lt; *p*−1 なる *h* に対して *g* = *h*(*p*–1)/*q* mod *p* なる *g* を求める。もし *g* が1となる場合には *h* を選択し直す(*h* の初期値としては 2がよく用いられる)。フェルマーの小定理より *g<sup>q</sup>* ≡ *h**p*&nbsp;&minus;&nbsp;1 ≡ 1 (mod&nbsp;*p*) が導かれる。*g*&nbsp;>&nbsp;1 かつ *q* が素数であるから、*g* は有限体F_p の乗法群F_p^*(位数 *p*-1) の位数 *q* の元である(つまり 0 &lt; *a* &lt; *q* である任意の整数 *a* について、*g<sup>a</sup>* &nequiv; 1 (mod *p*)である)。

### 鍵ペアの生成
パラメータ (*p*, *q*, *g*) を基に鍵ペアを生成する。
* 0 &lt; *x*&nbsp;x* mod *p* を計算する。*x* と *y* の対応は1対1であり、*x* から *y* を計算することは比較的容易だが、*y* から *x* を計算することは実質的に不可能([[離散対数]]問題)である。つまり *x* と *y* の対応は[[一方向性関数]]になっている。
* 公開鍵は (*p*, *q*, *g*, *y*)、秘密鍵は *x* である。

[[冪剰余]] *h*<sup>(*p*–1)/*q*</sup> mod *p* および *gx* mod *p* の効率的な計算法が存在する。[[冪乗#効率的な演算法]]を参照のこと。

パラメータ (*p*, *q*, *g*, *y*) は他者との間で共有される。例えば、[[公開鍵基盤]](PKI)を用いる場合は、これらは[[認証局]](CA) において署名者の情報と関連付けられて公開される。

== 署名 ==
ハッシュ関数を <math>H</math>、署名したいメッセージを <math>m</math> とする。
* <math>0 < k < q</math> なる <math>k</math> をメッセージごとにランダムに決定する。
* <math>r=\left(g^{k}\bmod\,p\right)\bmod\,q</math> を計算する
* もし <math>r=0</math> である場合には <math>k</math> を選択し直す。
* <math>s=k^{-1}\left(H\left(m\right)+xr\right)\bmod\,q</math> を計算する(<math>k^{-1}</math> は[[有限体]]<math>F_q</math> における <math>k</math> の逆元である)。
* もし <math>s=0</math> である場合には <math>k</math> を選択し直す(これは <math>H\left(m\right)+xr</math> が <math>q</math> の倍数の場合に起こる、非常なレアケースであり、<math>k</math> を変えることにより <math>r</math> が変わり、<math>s</math> が 0 でなくなる可能性が高い)。
* <math>\left(r,s\right)</math> が <math>m</math> に対する署名となる。

最初の2段階がメッセージごとの鍵を生成するステップである。冪剰余の計算が署名操作において最も計算量の多い過程であり、メッセージのハッシュを求める前に計算される。<math>k^{-1}\bmod\,q</math> が次いで計算量の多い過程であり、[[ユークリッドの互除法#拡張された互除法|拡張されたユークリッドの互除法]]あるいは <math>k^{q-2}\bmod\,q</math> として[[フェルマーの小定理]]を用いて計算されることがある。

== 検証 ==
メッセージ <math>m</math> と署名 <math>\left(r,s\right)</math> の検証は以下のように行われる。
* <math>0<r<q</math> かつ <math>0<s<q</math> を満たさない場合には拒否する。
* <math>w=s^{-1}\bmod\,q</math> を計算する。
* <math>u_{1}=H\left(m\right)\cdot w\,\bmod\,q</math> を計算する。
* <math>u_{2}=r\cdot w\,\bmod\,q</math> を計算する。
* <math>v=\left(\left(g^{u_{1}}y^{u_{2}}\right)\bmod\,p\right)\bmod\,q</math> を計算する。
* <math>v=r</math> であれば署名は正当なものである。

DSAは[[ElGamal署名]]の改良版であり、類似している。

== アルゴリズムの正当性 ==
DSAの署名スキームは、検証者が常に純正の署名を受け入れるという意味では[[正当性 (計算機科学)|正当]]である。それは以下のように証明される。

署名者は次式を計算する。

:<math>s=k^{-1}(H(m)+xr)\bmod\,q</math>

ゆえに

:<math>
\begin{align}
k & \equiv H(m)s^{-1}+xrs^{-1}\\
  & \equiv H(m)w + xrw \pmod{q}
\end{align}
</math>

前述のように *gq* ≡ 1 (mod *p*) であるから

:<math>
\begin{align}
g^k & \equiv g^{H(m)w}g^{xrw}\\
    & \equiv g^{H(m)w}y^{rw}\\
    & \equiv g^{u1}y^{u2} \pmod{p}
\end{align}
</math>

最終的に、DSAの正当性は以下に示される。

:<math>\begin{align}
 r &= (g^k \bmod\,p) \bmod\,q\\
   &= (g^{u1}y^{u2} \bmod\,p) \bmod\,q\\
   &= v
\end{align}</math>

== ランダム値の選択方法と安全性 ==
DSAにとって、署名の際のランダム値 *k* のエントロピー、機密性、唯一性は決定的に重要である。これら3つのうちの1つが破られることは、攻撃者に対して秘密鍵そのものが明かされることと等しい。*k* として同じ値を二度用いること（*k* を秘密にしていたとしても）、予測可能な値を用いること、複数の署名に対するそれぞれの *k* が数ビットであっても漏洩することは、DSAを破るには十分である。

*エントロピー(情報理論的エントロピー)：*k* のエントロピーは *k*を 1 から *q*-1 の間から選ぶ際のランダムさの偏りのなさを表す値(単位はビット)であり、大きいほど好ましい。常に同一の *k*を使い続ける場合にエントロピーは最小値0となり、最も秘匿性が脆弱になる。全くランダムに選ぶ場合はエントロピーは最大値 <math>\log_2 (q-1)</math> (ビット)となり、これは鍵長*N*にほぼ等しい。
*機密性：*k* は署名者側のアルゴリズムでだけ使われる整数値であり、外部に送信してはならない。*k* の値が外部に漏れた場合、攻撃者は外部に送信される *m*, *r*, *s* から
:<math>s=k^{-1}(H(m)+xr)\bmod\,q</math> 
によって秘密鍵 *x* の値 を計算可能になる。
*唯一性：同一の署名者は同じ *k* を用いて2つ以上の異なるメッセージに対して *r*, *s* を計算し送信してはならない。<math>r=(g^{k}\bmod\,p)\bmod\,q</math> により *k* が同じであれば、 *r* も同じであるので、攻撃者は同じ *k* を用いて計算された署名を容易に見破ることができる。今、同一の署名者が2つの異なるメッセージ *mA* と *mB* に対して同じ *k* を用いて署名 (*r*, *sA*) と (*r*, *sB*) を計算および送信し、攻撃者が2つのメッセージと署名を入手できたとすると、
:<math>s_A = k^{-1} (H(m_A)+xr)\bmod\,q</math> 
:<math>s_B = k^{-1} (H(m_B)+xr)\bmod\,q</math> 
であるから、上の2式の差を取ると *xr* の項が相殺されてしまい、
:<math>s_A - s_B = k^{-1}(H(m_A)-H(m_B) )\bmod\,q</math> 
となり、*k* の値が計算可能になる。*k* の値が分かれば上述のように秘密鍵 *x* の値も計算可能になる。

2010年12月、*fail0verflow* と名乗るグループが、[[ソニー]]が[[PlayStation 3]]のソフトウェア署名に用いていた[[楕円曲線DSA]]の秘密鍵の回復に成功したと発表した。これは、ソニーが署名ごとに新しいランダムな *k* を用いていなかったためである。

唯一性の問題は、にあるように、秘密鍵 *x* とメッセージハッシュ *H(m)* から決定論的に *k* を導くことで回避できる。これにより、*k* がそれぞれの *H(m)* に対して異なることと、秘密鍵 *x'' を知らない攻撃者にとって予測不能であることが保証される。

## 実装ライブラリ
DSAをサポートしているライブラリは以下のものがある。

* Botan
* Bouncy Castle
* cryptlib
* Crypto++
* libcrypt
* libsodium
* Nettle
* OpenSSL
* wolfSSL
* GnuTLS

## 脚注

## 関連項目
* 楕円曲線DSA
* ElGamal署名
* 合同式

## 外部リンク
* FIPS PUB 186-4: Digital Signature Standard (DSS), the fourth (and current) revision of the official DSA specification.
* Recommendation for Key Management -- Part 1: general, NIST Special Publication 800-57, p.&nbsp;62&ndash;63