楕円曲線DSA

**楕円曲線DSA**（だえんきょくせんDSA、*Elliptic Curve Digital Signature Algorithm*、*Elliptic Curve DSA*、**楕円DSA**、**ECDSA**）は、楕円曲線暗号における離散対数問題を用いたデジタル署名の一種であり、Digital Signature Algorithm (DSA) の強化版の一つである。

メッセージの送信者は、秘密鍵を決め、これに基づいて決めた公開鍵を、しかるべき権威を持った認証局においてあらかじめ公開しておき、秘密鍵を用いて送信メッセージに添付するデジタル署名を作成する。この際、メッセージの受信者の情報(受信者の公開鍵など)は必要なく、不特定多数の受信者に対して、デジタル署名付きのメッセージを送信可能である。

メッセージの受信者は、認証局から入手する暗号のパラメーターと送信者の公開鍵を用いて、以下で説明するアルゴリズムにより、デジタル署名の正当性を検証できる。検証の際に、受信者は送信者、認証局または第三者から、デジタル署名の正当性に関する追加の情報を得る必要はない(ゼロ知識証明)。

## DSAとの比較
ECDSAでは楕円曲線暗号における離散対数問題を用いて、公開鍵から秘密鍵の値が解読されるのを防いでいる。離散対数問題のセキュリティ強度(セキュリティ強度が  l (ビット)であるとは、攻撃者が公開鍵から秘密鍵を解読するために必要な単位操作の回数が  2^l 回程度であることを表している)は、公開鍵のサイズの約1/2である。例えば、80ビットのセキュリティ強度（攻撃者が秘密鍵を取得するために 2^{80} 回の計算を必要とする）を得るために、ECDSAでは160ビットの公開鍵が必要である。一方、DSAで同程度のセキュリティ強度を得るには最低でも1024ビットの公開鍵が必要である。なお、ECDSAでは、署名のサイズは、必要とするセキュリティ強度の4倍のビット長を要する（つまり、80ビットのセキュリティ強度を得るためには320ビットの長さの署名が必要である。詳細後述）。

アメリカ国立標準技術研究所(NIST)は、"Digital Signature Standard (DSS)規格書"(FIPS 186-5, February 3, 2023)の中で、理由は明示していないが「従来の DSA は本標準では取り扱わないことになった。ただし、本標準策定以前に行われた署名の検証には利用可能である」と述べており、「RSAデジタル署名」、「楕円曲線デジタル署名」、「エドワーズ曲線デジタル署名」の3種のデジタル署名の標準規格を規定している。

## 署名生成
アリスが署名したメッセージをボブに送る場合を考える。最初に、使用する楕円曲線のパラメータ (E(a,b), p, G, n) を決めておく必要がある。

次に、アリスは [1, n-1] の範囲からランダムに選択された秘密鍵 d_A と、公開鍵 Q_A = d_A * G から成る鍵ペアを生成する。d_A と  Q_A の対応は1対1であり、d_A から  Q_A を計算することは比較的容易だが、 Q_A から d_A を計算することは実質的に不可能(離散対数問題)である。つまり d_A と Q_A の対応は一方向性関数になっている。

これらのパラメータと公開鍵 Q_A は、しかるべき権威をもった認証局でネット上に公開される(当然、秘密鍵 d_A の値は認証局にも知らされない)。

:(注1) G、Q_A は \mathbf{F}_p \times \mathbf{F}_p  の元であり、\mathbf{F}_p の元 x および y の組 (x,y) から成る2次元ベクトル値である。これに対して a,b,p,n,d_A は整数であり、以降ベクトル値に対してスカラー値と呼ぶことにする(d_A は \mathbf{F}_n の元でもある)。また、以降、小文字で始まる変数はスカラー値、大文字で始まる変数はベクトル値とする。
:(注2)「*」はスカラー値とベクトル値の楕円曲線上での乗算 (scalar multiplication) を意味する。楕円曲線上での加算を「+」と表し、x,yは任意のスカラー値、Pは任意のベクトル値とする場合、これらは結合法則 (xy)*P = x*(y*P)、および分配法則 (x+y)*P = x*P + y*P を満たす。なお、P が G が生成する巡回群  の元の場合、スカラー値同士の乗算と加算は、\mathbf{F}_n における乗算と加算となる。

アリスがメッセージ m に署名する場合、以下の計算を行う。

# e = H(m) を計算する。ここで *H* はSHA-1のような暗号学的ハッシュ関数を指す。
# z を、e の最上位側の l_n ビットとする。ここで l_n は位数 n のビット長とする(つまり l_n は \log _2 n 以上の最小の整数である)。
# [1, n-1] の範囲から整数 k を任意に選択する。k を「1回秘密鍵」と呼ぶことにする。
# 曲線上の点 (x_1, y_1) = k * G を計算する。
# r = x_1\,\bmod\,n を計算する(\bmod\,p でないことに注意)。r = 0 となる場合には k の選択に戻る。
# s = k^{-1}(z + r d_A)\,\bmod\,n を計算する(k^{-1}は有限体\mathbf{F}_nにおけるkの逆元である)。s = 0 となる場合には k の選択に戻る。
# (r, s) が m に対する署名となる。
:(注3) s を計算する際に、H(m) から得られる z は整数に変換される。z は n より「大きい」ことは許されるが、「長い」ことは許されない。
:(注4) \mathbf{F}_n の 0 以外の任意の元 x の \mathbf{F}_n における逆元 x^{-1} は、フェルマーの小定理から x^{n-1} \equiv 1\,(\bmod \,n) であるから、x^{-1} = x^{n-2} \,\bmod \,n によって計算できる。
:(注5) 上記ステップ4と5において計算され、署名として公表される r の値から  k の値を求めることは離散対数問題であり、実質的に不可能である。従って r を公表しても k の値の秘密は保たれるとしてよい。
:(注6) 一般に、離散対数問題のセキュリティ強度 l は n のビット長 l_n の1/2になる。署名 r と s のビット長は最大で l_n と同程度になるので、署名全体のビット長はセキュリティ強度 l の4倍必要になる。

もし、1回秘密鍵 k の値が外部に漏れた場合は、ステップ6において計算され、r と共に署名として公表される s の値から、ステップ6の式によって d_A の値を逆算できることになり、アリスの署名の信頼性は壊滅することになる。

k の値が外部に漏れる最もあり得るケースは、異なるメッセージに対して、同一の k を用いて署名を行う場合である。この場合、以下のようにして、ステップ6の式から秘密鍵 d_A を得ることが可能となってしまう(これはDSAの場合でも同様である)。

2つの異なるメッセージ m および m' に対して、攻撃者にとっては未知だが同じ1回秘密鍵 k から得られた2つの署名がある場合、署名生成のステップ4とステップ5から、この2つの署名の r も同じ値になる。攻撃者は多数の署名付きメッセージから  m は異なるが r が同じものを選び出す。これらの署名付きメッセージを (m, r, s) および (m', r, s') とする。攻撃者は z および z' を計算することが可能であり、s - s' = k^{-1}(z - z') であることから、k = \frac{z - z'}{s - s'} が得られる。s = k^{-1}(z + r d_A) であるから、攻撃者は秘密鍵 d_A = \frac{s k - z}{r} を得ることができる。

特に全てのメッセージに対して単一の k を用いることは極めて不適切な実装であり、PlayStation 3のソフトウェア署名鍵が漏洩したのはこれが原因であった。

## 署名検証
ボブがアリスの署名を検証するためには、アリスの公開鍵 Q_A が必要である。公開鍵 Q_A が正当なものであるかの検証は以下のとおりである。

# Q_A が O でないことを確認する。
# Q_A が曲線上にあることを確認する。
# n * Q_A = O であることを確認する。

メッセージ m と署名 (r, s) の検証は以下のように行われる。

# r および s がいずれも [1, n-1] の範囲にある整数であることを確認する。これを満たさない場合には署名は不正なものである。
# e = H(m) を計算する。ここで *H* は署名生成に用いられたハッシュ関数と同一のものである。
# z を、e の最上位側の l_n ビットとする。
# s^{-1} を計算する。
# u_1 = zs^{-1}\,\bmod\,n および u_2 = rs^{-1}\,\bmod\,n を計算する。
# 曲線上の点 (x_1, y_1) = u_1 * G + u_2 * Q_A を計算する。
# r \equiv x_1 \pmod{n} であれば署名は正当なものである。

Straus's algorithm（Shamir's trickとも）を用いることで、2つの楕円曲線上での掛け算の和 u_1 * G + u_2 * Q_A を、2つの楕円曲線上での掛け算よりも速く計算することができる。

## 署名検証アルゴリズムの説明
メッセージ m に対する署名 (r, s) が、秘密鍵 d_A の値を知っている者によって正しく生成されたものと仮定する。

C を署名検証のステップ6で得られた点(x_1, y_1)とする。つまり、

C = u_1 * G + u_2 * Q_A

公開鍵が Q_A = d_A * G と定義されているので、結合法則を適用して、

C = u_1 * G + (u_2 d_A) * G

楕円曲線上での乗算と加算の分配法則を適用して、

C = (u_1 + u_2 d_A) * G

署名検証のステップ5から

C = (z s^{-1} + r d_A s^{-1}) * G

s^{-1} を外に出して

C = (z + r d_A) s^{-1} * G

s^{-1} = (k^{-1} (z + r d_A))^{-1} = k (z + r d_A)^{-1}\,\bmod\,n

C = (z + r d_A) (z + r d_A)^{-1} k * G

(z + r d_A)^{-1}は有限体\mathbf{F}_n における (z + r d_A) の逆元であるから (z + r d_A) (z + r d_A)^{-1} = 1\,\bmod\,n である。これから

C = (x_1,y_1) = k * G

署名の作成者は、秘密鍵 d_A の値を知らなくても、1回秘密鍵 k の値を自分で決めて、署名生成のステップ4とステップ5によって r の値を求めるまでのことは可能であるが、d_A の値を知らない場合は、署名生成のステップ6の s の値を正しく決めることはできない。

署名検証のステップ7、つまり r \equiv x_1 \pmod{n} が成立するということは、上記の最後の式が成立しているということであり、これは署名の作成者は、s の値を正しく決めていたことを意味する。このためには署名の作成者は d_A の値を知っている必要があり、最初の仮定「署名の作成者は秘密鍵 d_A の値を知っている」が肯定されることになる。

なお、以上は秘密鍵 d_A の値を知っている者が、正しく署名したメッセージは、正しく検証されるということを示しているが、秘密鍵 d_A の値を知っている者が、本当にアリスであるかは別問題である。例えば前述のように、異なるメッセージに対して、同一の1回秘密鍵 k を用いて署名した場合、 k の値を解読されて、さらにこれから d_A の値も解読されることになる。

## セキュリティ
2010年12月、fail0verflowと名乗るグループが、ソニーがPlayStation 3のソフトウェア署名に用いていたECDSA秘密鍵の回復に成功したと発表した。しかし、これは k をランダムではなく固定値としていたソニーの不適切な実装によるものであり、アルゴリズム自体の脆弱性ではない。署名生成のセクションで述べたように、k を固定値で用いることは秘密鍵 d_A を計算可能とし、アルゴリズムを破綻させるものである。

2011年3月29日、2人の研究者による論文がに発表された。この論文では、サイドチャネル攻撃の一つであるタイミング攻撃によって、ECDSAを認証に利用し、OpenSSLを用いたサーバのTLS秘密鍵を入手可能であることが示された。この脆弱性はOpenSSL 1.0.0eで修正された。

2013年8月、Java class SecureRandomのいくつかの実装において、k のコリジョンが発生することがあるバグが明らかとなった。前述のように、これにより秘密鍵を得ることが可能であり、Javaを利用しECDSAを認証に用いていたAndroidアプリからBitcoinが盗まれる危険性があった。この問題は独立提出のにあるように、秘密鍵とメッセージハッシュから決定論的に k を導くことで回避できる。

2015年1月、Bitcoinのウォレットが完全にオフラインであっても、ECDSAを利用したトランザクションのデジタル署名を通して秘密鍵が漏洩される可能性があることを示す研究論文がarXivにて発表された。この論文では、利用ユーザー側がECDSAおよびビットコインの実装を完全に検証できない限り信頼できないことから、ソースコードの検証からコンパイルといったユーザー側の敷居が高くなるため、プライベートキー漏洩の攻撃を防ぐための実質的な解決策が現段階でないと結論付けている。

このアルゴリズムは楕円曲線をパラメータとして必要とするが、多くの場合NISTによって定められた楕円曲線（P-256、P-384、P-521など）が用いられる。これらの曲線は特定のシード値からSHA-1を基盤としたアルゴリズムを用いて算出されているが、シード値の根拠が不明であること、また同じく固定の楕円曲線を用いたアルゴリズムであるにNSAがバックドアを仕込んだ上でRSAセキュリティ社のセキュリティ製品に採用させたと報道されたことから、疑いの目で見られることがある。

## 実装ライブラリ
ECDSAをサポートしているライブラリは以下の通りである。

* Botan
* 
* 
* 
* 
* OpenSSL
* GnuTLS
* wolfCrypt

## 脚注

## 参考文献
* Accredited Standards Committee X9, *American National Standard X9.62-2005, Public Key Cryptography for the Financial Services Industry, The Elliptic Curve Digital Signature Algorithm (ECDSA)*, November 16, 2005.
* Certicom Research, ''Standards for efficient cryptography, SEC 1: Elliptic Curve Cryptography'', Version 2.0, May 21, 2009.
* López, J. and Dahab, R. ''An Overview of Elliptic Curve Cryptography'', Technical Report IC-00-10, State University of Campinas, 2000.
* Daniel J. Bernstein, Pippenger's exponentiation algorithm, 2002.
* Daniel R. L. Brown, *Generic Groups, Collision Resistance, and ECDSA*, Designs, Codes and Cryptography, **35**, 119–152, 2005. ePrint version
* Ian F. Blake, Gadiel Seroussi, and Nigel P. Smart, editors, *Advances in Elliptic Curve Cryptography*, London Mathematical Society Lecture Note Series 317, Cambridge University Press, 2005.
* 

## 関連項目
* 楕円曲線暗号
* Digital Signature Algorithm

## 外部リンク
* Digital Signature Standard; includes info on ECDSA