読者です 読者をやめる 読者になる 読者になる

clock-up-blog

go-mi-tech

簡易的な電子署名の実践(印鑑の文化との比較)

なんでもセキュリティ Advent Calendar 2016 8日目の記事です。

古典的な署名

時代を遡れはキリが無いがお手軽に皆が理解している署名は印鑑による押印だろう。
(特にここでいう印鑑とは印鑑登録済みの実印をイメージしていただきたい)

要はある契約(書類)に対して誰かしらが同意したことを示す物証が署名である。
印鑑は(性善説に基づけば)唯一無二の存在なので、ある個人または組織の印鑑が押された契約書類があるということはつまり、その個人または組織がその契約内容に同意したことを示す物証となる。

印影・印鑑は偽造され得る

押印済みの陰影を、写真で撮るなりスキャンするなりセロテープで上澄みのインクを剥がし取るなどして、正確に近い陰影は盗まれ得る。盗まれた印影を元に判子職人ががんばってそれを真似て作れば本物と極めて区別の付きにくい印鑑ができあがる。

バレると刑法により罰せられるので普通の人はやらないだろうが普通じゃない人に関わる場合には気を付けたほうが良い。

※ひと昔前であれば偽造技術にもある程度のハードルがあったものだが今となってはいくらでも偽造手段があり危なっかしい

電子の力を借りて署名を行う

これまでにいくつか署名関連の記事を書いたが、仕組みの詳細には触れていない。

というわけで電子署名の解説に入る

まず、電子署名を行いたい者は秘密鍵公開鍵のペアを作成する。

まず、秘密鍵というのは任意ビット数のバイナリである。ここに組織情報等は含まれない。単なるランダムなビット列(バイト列)と考えていただければよろしい。

公開鍵もまた同じく単なるビット列(バイト列)である。それ以上の情報は含まれない。

登場人物

今回は以下の登場人物を想定する。

  • 送信者A
  • 受信者B
  • 悪者X

送信者A:秘密鍵の生成 (private.pem)

$ openssl genrsa 2048 > private.pem

これで private.pem という 2048 ビット長の秘密鍵ができあがる。

中身

$ cat private.pem 
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEArpjN+Jw+Iv7MI+nV5a/8BghjOflKfsmkoVB88S5DzCfdXVcJ
....
9WdEdFF8spDyhPzujcrXo7/63XmrP5D35tKbt+qr1GkOdqbfTxlMig==
-----END RSA PRIVATE KEY-----

送信者A:公開鍵の生成 (public.pem)

$ openssl rsa -in private.pem -pubout > public.pem

秘密鍵に対応した公開鍵ができあがる。(秘密鍵さえあれば公開鍵はいつでも作り直せる)

中身

$ cat public.pem 
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArpjN+Jw+Iv7MI+nV5a/8
....
CwIDAQAB
-----END PUBLIC KEY-----

秘密鍵と公開鍵の在り方について

ここが割と重要なことだったりするのだが、

  • この秘密鍵が実世界でいうところの「印鑑」に相当し、
  • この公開鍵が実世界でいうところの「印影」に相当する

一般的に実世界での印鑑についてはその印鑑の所有者を証明するための印鑑登録証明書というものが存在する。これは市区町村や法務局等に対して登録の申請を行い、発行してもらうものであり、ここには印影とその所有者の名前や住所等の情報が記載されたものである。この証明書により、印影と個人情報が紐づいていることが公的に証明される。(ちなみに登録に際しては手数料がかかる)

電子署名についても同様の仕組みが存在する。
認証局(CA)というものがいくつか存在し、そこに公開鍵(印影に相当する)と所有者情報を登録し、公開鍵証明書というものを発行してもらう。この証明書には公開鍵とその所有者の名前や住所等の情報が含まれる。(これもまた登録に際しては手数料がかかる。無料のところも実はあるが)

送信者A:秘密鍵による署名

以下テキスト test.txt に署名を行ってみることにする。

$ cat test.txt 
It's sunny today
-----
kobake 2016/12/7


test.txt に対し、秘密鍵 private.pem を用いて署名ファイル test.txt.sig を作成する。

$ openssl dgst -sha1 -sign private.pem test.txt > test.txt.sig


署名ファイルは完全なバイナリなので hexdump 等で中身を見ると良い。

$ hexdump test.txt.sig
0000000 3b13 d77a 4312 58de 8142 a825 99d3 9eed
0000010 8ff9 66fa d7bd e6e3 8db5 5d9e dd43 bef1
....
00000f0 38e0 ed3e e55d 30fc 1c71 a9c8 7869 a4f6
0000100


さきほど、公開鍵 (public.pem) が印影に相当する、と書いたが、
この署名ファイル test.txt.sig は「文書 test.txt に押された印影」に該当する。

送信者A:元文書と署名の送付

さて、文書に署名をする以上は、その文書を誰かに送るときである。
ということで今回の場合は test.txt および test.txt.sig を受信者Bに送るものとする。(送り方はメールでも何でも良い)

受信者B:受け取った側での署名の検証

今回は test.txt および test.txt.sig を受け取ったが、test.txt は別段暗号化されているわけでもないため、そのまま中身を閲覧することができる。
その test.txt の中身を本当に信頼しても良いものかどうか判断するために、送信者Aの署名であるところの test.txt.sig が用いられる。

まず、送信者Aの元の印影に相当する公開鍵を得るために公開鍵証明書を取得する。。としたいところなのだが、今回は簡易的に公開鍵情報は既に送信者Aがどこかに提示している、ということにする。(公開鍵は名前の通り、常に公開しておいて支障のないものである。例えば GitHub 等では任意ユーザの公開鍵を誰でも見ることができる。例えばこんな感じ→ https://github.com/kobake.keys)

そんなわけで受信者Bが手に入れたファイルは以下の3つである。

  • test.txt … 文書本体。中身はそのまま見れる。
  • test.txt.sig … 送信者Aの署名
  • public.pem … 送信者Aの公開鍵

文書が正しく署名されているかどうかは以下のコマンドにより確認できる。

$ openssl dgst -sha1 -verify public.pem -signature test.txt.sig test.txt
Verified OK

このように「Verified OK」と出れば正しく署名されていたことが確認できたことになる。
逆に誤った署名であった場合、「Verification Failure」のような表示となる。

この確認により、test.txt が確実に送信者Aにより署名されたことが保証される。


ところで技術の話ではなく社会の話になるのだが、今回の検証により保証されるのは「test.txt が送信者A により署名された事実」だけであり、必ずしも test.txt の内容が正しい、ということではない。送信者Aが錯誤により test.txt に署名を行ってしまった可能性もあるからである。

悪者X:署名の偽造は可能かどうか

たとえば以下のような(さきほどとは内容の違う)テキストに対して、送信者Aとは別人の悪者Xが、さきほどと同じ送信者Aが署名したかのように署名ファイルを作ることは可能かどうか。

$ cat test2.txt 
It's rainy today
-----
kobake 2016/12/7


この test2.txt への署名には以下のようなコマンドが必要となる。

$ openssl dgst -sha1 -sign private.pem test2.txt > test2.txt.sig

ここで private.pem (秘密鍵) が必要になるのだが、この秘密鍵は送信者Aのみが所有しており、公開されているものではない。
よって悪者Xは送信者Aのように振舞った署名を行うことはできない。

秘密鍵と公開鍵の関係について

RSA鍵システムの仕組み上、秘密鍵から公開鍵を生成することはできるが、その逆はできない。簡潔にいうと秘密鍵は2つの大きな素数を保持しており、公開鍵はその素数の積により構築されている。大きな数の素因数分解はとても難しいため、基本的に(時間がかかりすぎるという意味で)不可能であり、公開鍵を公開していてもそこから秘密鍵が復元される可能性は限りなく低い、とされている。

冒頭で示したように、実世界における印鑑と印影においては印影をもとに印鑑を偽造する難易度が比較的低めであるのに対し、電子署名においては公開鍵(印影)から秘密鍵(印鑑)を偽造することが極めて難しいため、偽造に対する耐性という点においては電子署名の安全性は高いと言える。

おわりに

リアル印鑑を使おうが電子署名を使おうがこれは変わらないことなのだが、「リアル印鑑の実物を盗まれたり」「秘密鍵ファイルを盗まれたり (※1)」したら当然署名は悪用され得る。

大事なものは盗まれにくい場所に閉まっておきましょう。

});