ちょっと話題の記事

非エンジニアに捧げる公開鍵暗号方式

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。インターン生の春田です。

今回は基本的な内容ですが、ブロックチェーンで「信用」を担保している「公開鍵暗号方式」について説明していきます。

学部の卒論の定期発表で、IT技術に馴染みのないゼミ生や教授に説明した時に使ったレジュメが元になっています。

※(2018/6/4 改訂) ご指摘をいただき、一部加筆修正しています。修正箇所が多く、読みづらくなってしまうので、改訂箇所はまとめて一番下の節で解説しています。

公開鍵暗号方式

公開鍵暗号方式 は、暗号化技術の一つです。公開鍵暗号方式は、 秘密鍵(Private Key)公開鍵(Public Key) という、2種類の対になる鍵のペアで実装されています。ここでいう「鍵」というのは、人間がわかりやすく理解するために抽象化された概念であり、実際には複雑な数字の羅列からできています。

例えば、AさんがBさんに機密情報ファイルをメールで送信する時、情報漏えいを防ぐためにファイルをロックし、Bさんだけが開けられるように手配する必要があります。この時、まずBさんの下で秘密鍵と公開鍵を作成し、何らかの安全な方法で公開鍵だけをAさんに渡します。Aさんは受け取った公開鍵を使って、機密情報ファイルを暗号化し、Bさんに送信します。Bさんは、機密情報ファイルを手元にある秘密鍵を使って復号することで、中身を閲覧できるようになります。以下、詳しく説明していきます。

秘密鍵と公開鍵 (Private Key & Public Key)

一般的に「鍵」と言えば、金庫を例にすれば、「金庫」と「鍵」があり、鍵を使って金庫を開閉することができます。また鍵を複製することで、別の人もその金庫を開閉することができます。

これをコンピューター上の暗号方式に置き換えると、鍵を閉める行為は 暗号化 、鍵を開ける行為は 復号 に当てはまります。(復号化ではないのでご注意。)この暗号化を公開鍵が、復号を秘密鍵が担っており、2種類の鍵があって初めて「鍵」としての機能を果たすことができます。では、なぜ2種類の鍵が必要なのでしょうか?ここで重要になるのは、公開鍵暗号の持つ 非対称性(Asymmetricity) です。

上は公開鍵暗号方式をイメージ化したものです。この特殊な鍵穴はロックする箇所がAとBの2箇所あり、秘密鍵は時計回り方向(A -> B -> C)、公開鍵は反時計回りの方向(C -> B -> A)にしか回すことができないのが特徴です。このOne-Wayな鍵の仕組みのことを 非対称(Asymmetric) であると表現されます。

先ほどの例でいうと、機密情報ファイルの送信者は公開鍵を使って鍵穴を反時計周りに回し、Aの位置でロックした後ファイルを送信します。一方、受信者は秘密鍵を使って鍵穴を時計回りにBの位置まで回し、ファイルのロックを解除することができます。

「なぜ2種類の鍵を用意する必要があるのか?」という疑問が湧いてきますが、鍵の「複製」という観点から考えると大きなメリットがあります。秘密鍵はその名の通り、所有者が厳重に保管しなければならない鍵で、セキュリティ的に複製が難しいです。仮に秘密鍵が漏洩してしまった場合、対応する公開鍵で暗号化した機密情報ファイルを全て回収しなければなりません。(普通に考えて無理です。)一方、公開鍵はファイルをロックすることだけしかできないため、容易に複製することができます。このため秘密鍵の所持者は、その秘密鍵さえ守れば、公開鍵の管理は別段気にかける必要がなく、公開鍵を複製することによって、複数のユーザーとセキュアに通信することができます。仮に、秘密鍵も公開鍵も全く同じ機能であったとしたら、秘密鍵の所持者は渡した公開鍵まで監視していかなければならなくなり、安全性を保証できず不便です。

以上から、インターネット上では秘密鍵と公開鍵を分けて使用することで、(理論上では)機密情報を安全にやりとりすることができます。

さて、ここまでで鍵穴のAB間の説明をしましたが、Cまで回せるのは何を意味しているのでしょうか?鍵穴BC間は、実際のファイルの開閉を表現しているのではなく、次に説明する デジタル署名 (Digital Signature) について表しています。

デジタル署名 (Digital Signature)

今度は逆に、秘密鍵を持つ送信者が公開鍵を持つ受信者にファイルを送信する場合、送信者は秘密鍵を使って、「確実にその送信者が送信したファイルであるか」「そのファイルが改ざんされていないか」を確認できる「情報」を付与して受信者に送信することができます。この情報のことを デジタル署名 (Digital Signature) と呼びます。

送信者は送りたいファイルに、唯一無二の秘密鍵で作成したデジタル署名という情報を添付して送信し、受信者は手元の公開鍵を使って秘密鍵の独自性を検証できれば、確実に送信者が送信したファイルであると確認することができます。これを上の例でいえば、送信者が秘密鍵でBからCの位置にロックし、受信者はCからBへロックを解除できれば、Aさんが送信したファイルであるという確証が得られます。

ファイルが改ざんされたかどうかを確認するには、先ほどまで曖昧に表現していた、デジタル署名という「情報」に仕組みがあります。公開鍵暗号を元にしたデジタル署名では、ここでいう「情報」とは一般に、ファイルの ハッシュ値 という値に対して秘密鍵を使った特殊な演算をしたものです。ハッシュ値とは、ファイルを ハッシュ関数 というもので計算することによって求められる値で、

  1. ファイルからハッシュ値は求められるが、ハッシュ値からファイルを復元することはできない。
  2. 同じファイルからは、同じハッシュ値が出力される。
  3. ファイルを少しでも改ざんすると、ハッシュ値が大きく変わる。

という特徴があります。ひらがなや漢字がどうして関数の引数になるのか、という疑問があるかもしれませんが、そもそもコンピューター上では、全ての文字が元をたどれば0か1だけで表されているため、文字列も関数に通すことが可能です。送信者のハッシュ値が、受信者が受け取ったファイルから算出されるハッシュ値と一致した場合、「そのファイルは送信途中で改ざんされなかった」と判断することができます。

補足:
「秘密鍵で暗号化!公開鍵で復号!」と言いたいところなのですが、上でも説明した通り、秘密鍵は復号、公開鍵は暗号化しかできないので少々周りくどい表現になっています。公開鍵暗号方式を応用したらデジタル署名のような使い方もできるのでは?という発想が元であり、そもそもデジタル署名と公開鍵暗号方式は背景の異なる別の技術です。

署名に求められるものは本人しかできないという独自性であって、秘匿を目的とした暗号化とは異なるものですし、検証はあくまで整合性を確認するものであって、何かを復元したいわけではありません。(電子署名の基礎知識 より引用)

以上から、Bさんはデジタル署名によって、ファイルが改ざんされておらず、Aさんが送信したファイルであると確認することができました。Bitcoinではコインの受け手は、このデジタル署名を用いて、コインの送信者と取引が改ざんされていないかを確認しています。「署名」と名付けられている所以は、秘密鍵をまさに「印鑑」のように使っているからですね。(ちなみに、前述の鍵AB間、ファイルそのものを暗号化する技術は使われていません。)

Bitcoin上でのデジタル署名

公開鍵暗号方式において、公開鍵・秘密鍵は一般的に、 RSA暗号 を使って生成されます。RSAでは大きな素数(p,q)が与えられたとき、その積 pq=n を計算することは容易であるが、n=pqへ素因数分解することは難しい、という素因数分解の困難性に基づいています。

一方、Bitcoinのデジタル署名では ECDSA (Elliptic Curve Digital Signature Algorithm) というアルゴリズムが基になっており、秘密鍵は「2進数で256桁の数字」、公開鍵は「秘密鍵に楕円曲線暗号 (Elliptic Curve Cryptography)で計算した数字」で表されます。この楕円曲線暗号は、RSA暗号よりもアルゴリズムが強固で、そのため鍵長を短くすることができるという特徴があります。

公開鍵認証方式のデジタル署名を使ったBitcoinの取引の仕組みは、下の図のようになります。Bitcoinでハッシュ値が出力される元のデータは、誰が誰にいくら送金したかを記録する、帳簿式のトランザクションデータです。

まず、Sender(送金者)側でトランザクションデータのハッシュを計算し、Private Key(秘密鍵)で署名します。その後、Receiver(受金者)にPublic Key(公開鍵)と署名済みのハッシュ値を送信します。最後に、Receiver側でトランザクションデータのハッシュ値の計算と、署名されたハッシュ値の検証を行い、値が一致すれば「これは正しい送金である」と、Receiverは確証を得ることができます。

今回はBitcoinのトランザクションについてあまり触れられませんでしたが、上図の範囲で簡単に補足します。

Bitcoin Address

Private KeyとPublic Keyに紐付けられた、現実世界でいうと銀行口座の番号です。Public Key自体をハッシュ関数で計算するとBitcoin Addressが生成されます。Private Key → Public Key → Bitcoin Addressの3段階の不可逆変換(One-Wayな計算のこと)を行うことで、セキュリティをより強固なものにしています。

Walletなどの仮想通貨のアプリ上では、このAddressからAddressへと送金が行われています。

Transaction Data

一番下はBitcoinのトランザクションです。ビットコインの取引履歴の一部であり、これが積み重なり、全体で大きな台帳のようになっています。左側のInputは送金者がいくら送金したか、右側のOutputは受金者の受金額と、いわゆる「お釣り」と「手数料」が書かれています。

追記 : <誤解していた内容の要約>

記事に関してご指摘をいただきました。ありがとうございます。

もう一度調べ直してみたのですが、以下の記事を見て驚愕しました。

電子署名の基礎知識
「電子署名=『秘密鍵で暗号化』」という良くある誤解の話

そもそも私の誤解が多い!
読んでくださった方々、大変申し訳ありませんでした…

と、少し思ったのですが、super duper blooperさん以外からはご指摘を頂かなかったので、もともと同じように勘違いしていた方もいらっしゃるのではないでしょうか?
どこが間違っていたのか、という解説とお詫びの節です。

秘密鍵と公開鍵 (Private Key & Public Key)

これをコンピューター上の暗号方式に置き換えると、鍵を閉める行為は 暗号化 、鍵を開ける行為は 復号 に当てはまります。(復号化ではないのでご注意。)秘密鍵と公開鍵は、どちらも暗号化・復号することができますが、秘密鍵同士・公開鍵同士では復号することができないようになっています。すなわち、秘密鍵でロックしたものは公開鍵で、公開鍵でロックしたものは秘密鍵でしか解除することができません。では、なぜ2種類の鍵が必要なのでしょうか?ここで重要になるのは、公開鍵暗号の持つ 非対称性(Asymmetricity) です。

  • 取り消し線部 → 「この暗号化を公開鍵が、復号を秘密鍵が担っており、2種類の鍵があって初めて「鍵」としての機能を果たすことができます。」

秘密鍵で暗号化はできません。
angel_p_57さんの上の記事によりますと、世間に広まってしまっている「秘密鍵で暗号化」とは、実際には「秘密鍵で復号する演算とほぼ同じ処理を、平文に対して行う」ことだそうです。暗号化している訳ではありません。

さて、ここまでで鍵穴のAB間の説明をしましたが、Cまで回せるのは何を意味しているのでしょうか?鍵穴BC間は、実際のファイルの開閉を表現しているのではなく、次に説明する デジタル署名 (Digital Signature / Digital Fingerprint) について表しています。

  • "Digital Fingerprint"を消去。

デジタルフィンガープリントはまた別の概念です。

デジタル署名 (Digital Signature / Digital Fingerprint)

  • "Digital Fingerprint"を消去。

今度は逆に、秘密鍵を持つ送信者が公開鍵を持つ受信者にファイルを送信する場合、送信者は秘密鍵を使って、「確実にその送信者が送信したファイルであるか」「そのファイルが改ざんされていないか」を確認できる情報を付与して受信者に送信することができます。この情報のことを デジタル署名 (Digital Signature) と呼びます。送信者は送りたいファイルに、唯一無二の秘密鍵で暗号化したデジタル署名を添付して送信し、受信者は手元の公開鍵を使ってそれを復号できれば、確実に送信者が送信したファイルであると確認することができます。これを上の例でいえば、送信者が秘密鍵でBからCの位置にロックし、受信者はCからBへロックを解除できれば、Aさんが送信したファイルであるという確証が得られます。

  • 取り消し線部 → 「唯一無二の秘密鍵で作成したデジタル署名という情報を添付して送信し、受信者は手元の公開鍵を使って秘密鍵の独自性を検証できれば、」

仮に「暗号化」という表現を用いたとしても、暗号化されるのは「デジタル署名」ではなく「デジタルフィンガープリント」です。
「デジタル署名」は、秘密鍵を使って署名すること、独自性を保証するための技術のことを指します。

ファイルが改ざんされたかどうかを確認するには、先ほどまで曖昧に表現していた、デジタル署名という「情報」に仕組みがあります。このデジタル署名という「情報」は、ファイルの ハッシュ値 という値を秘密鍵で暗号化したものです。ハッシュ値とは、ファイルを ハッシュ関数 というもので計算することによって求められる値で、

  • 取り消し線部 → 「公開鍵暗号を元にしたデジタル署名では、ここでいう「情報」とは一般に、ファイルの ハッシュ値 という値に対して秘密鍵を使った特殊な演算をしたものです。」

ここでは、「『公開鍵暗号方式においての』デジタル署名では」という一言が必要でした。デジタル署名「一般」には当てはまりません。

Bitcoin上での公開鍵暗号方式

  • 取り消し線部 → 「デジタル署名」

この節の具体例では、Bitcoinでの「デジタル署名」について話しています。

一般的な公開鍵・秘密鍵は、 RSA暗号 を使って生成されます。RSAでは大きな素数(p,q)が与えられたとき、その積 pq=n を計算することは容易であるが、n=pqへ素因数分解することは難しい、という素因数分解の困難性に基づいています。一方、Bitcoin上では、秘密鍵は「2進数で256桁の数字」、公開鍵は「秘密鍵に 楕円曲線暗号 (Elliptic Curve Cryptography) で計算した数字」で表されます。この楕円曲線暗号は、RSA暗号よりもアルゴリズムが強固で、そのため鍵長を短くすることができるという特徴があります。

  • 取り消し線上部 → 「公開鍵暗号方式において、公開鍵・秘密鍵は一般的に、 RSA暗号 を使って生成されます。」
  • 取り消し線下部 → 「一方、Bitcoinのデジタル署名では ECDSA (Elliptic Curve Digital Signature Algorithm) というアルゴリズムが基になっており、秘密鍵は「2進数で256桁の数字」、公開鍵は「秘密鍵に楕円曲線暗号 (Elliptic Curve Cryptography)で計算した数字」で表されます。」

話の延長で「公開鍵暗号」について話しているように見えますが、実際は「デジタル署名」に話がすり替わっています。
「公開鍵暗号」ではなく「デジタル署名」を切り口に説明していくべきだったなと反省しています。かなりわかりにくい文章になってしまいました。

まず、Sender(送金者)側でトランザクションデータのハッシュを計算し、Private Key(秘密鍵)で暗号化します。その後、Receiver(受金者)にPublic Key(公開鍵)と暗号化したハッシュ値を送信します。最後に、Receiver側でトランザクションデータのハッシュ値の計算と、暗号化されたハッシュ値の復号を行い、値が一致すれば「これは正しい送金である」と、Receiverは確証を得ることができます。

  • 暗号化→署名
  • 復号→検証

以上となります。他気づいた点などございましたら、ご指摘いただければと思います。

まとめ

本記事では、一般的な公開鍵暗号方式の説明から、デジタル署名への応用、Bitcoinにおいての応用例を紹介しました。公開鍵・秘密鍵の技術は、拡張性が高く、様々なところで応用されており、コンピュータが通信する上でなくてはならない技術となっています。具体的な計算方法など、細かい部分について僕自身も勉強中です。
なんとなく概要を掴めていただけたら幸いです。

参照: