電子署名は、本人と無改ざんの証明
電子署名とは、データを送った人が本人であり、中身が途中で変わっていないことを、秘密鍵を使って確かめられるようにする仕組みです。印鑑やサインのデジタル版にあたります。
ソフトの更新や、ウェブサイトへの接続の安全は、この署名に支えられています。署名を信じる根拠になるのが、証明書です。
このレッスンのゴール
メモ
署名と証明書が、送り主と無改ざんを証明するしくみを説明することができる。
キーワード
| ことば | いみ |
|---|---|
| 電子署名 | 秘密鍵で作る、本人と無改ざんの証拠 |
| 検証 | 公開鍵を使って、署名が正しいか確かめること |
| 証明書 | 公開鍵が持ち主のものだと保証する電子的な書類 |
| 認証局 | 証明書に署名して、持ち主を保証する組織 |
| 信頼の連鎖 | 証明書が次々に署名され、最初の信頼できるものにつながる並び |
| ルート証明書 | 連鎖の出発点。機器が最初から信頼している |
学生が入力するセルは、このプレビューでは空白です。
署名は、秘密鍵で作って公開鍵で確かめる
暗号では、公開鍵で閉めて秘密鍵で開けました。署名はその逆です。秘密鍵で署名を作り、公開鍵で検証します。
秘密鍵を持つのは本人だけなので、公開鍵で検証が通れば、署名したのは本人だと分かります。文書全体ではなく、ハッシュ値に署名するのがふつうです。
例: ハッシュ値50に署名する
| 手順 | 誰が | 計算 | 結果 |
|---|---|---|---|
| 署名を作る | 送る人(秘密鍵) | 50 を103乗して143で割った余り | 106 |
| 検証する | 受け取る人(公開鍵) | 106 を7乗して143で割った余り | 50 |
| 改ざんを見つける | 受け取る人 | 届いたハッシュ値が51なら、50と合わない | 検証は失敗 |
学生が入力するセルは、このプレビューでは空白です。
秘密鍵で署名を作る
python3 -c "print(pow(50, 103, 143))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
公開鍵で検証する
python3 -c "print(pow(106, 7, 143))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
内容が変わっていたら
python3 -c "print(pow(106, 7, 143) == 51)"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
共通鍵で作る認証コードとの違い
共通鍵とハッシュ関数を組み合わせたHMACでも、改ざんは見つけられます。ただし、鍵を知る人なら誰でも、同じ認証コードを作れます。
署名は、秘密鍵を持つ本人しか作れません。後から「私は署名していない」と言い逃れるのが難しくなります。
共通鍵で認証コードを作る
python3 -c "import hmac, hashlib; print(hmac.new(b'key', b'message', hashlib.sha256).hexdigest())"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
公開鍵が本物だと、どう分かるのか
署名の検証には、本人の公開鍵が必要です。ところが、偽物の公開鍵を渡されたら、偽物の署名が通ってしまいます。
そこで証明書を使います。証明書は、「この公開鍵はこの持ち主のものだ」という文章に、認証局が署名したものです。
よくある間違い
注意
「鍵のマークが出ているから、そのサイトは安全で信頼できる店だ」と考える人が多くいます。証明書が保証するのは、通信が守られ、持ち主の名前が合っていることだけです。サイトの運営者が誠実かどうかは、別の問題です。
証明書の連鎖は、4つの点で確かめる
ブラウザは、サイトの証明書から順にたどって確かめます。1. 各証明書の署名は、次の証明書の公開鍵で検証できるか。2. 名前と発行者がつながっているか。
3. どれも有効期限が切れていないか。4. 最後がルート証明書で、機器が信頼しているものか。1つでも欠ければ、接続は警告になります。
Python で署名と検証を追う
# 小さな数の RSA で、署名と検証を手で追います。
n = 143
d = 103 # 秘密鍵: 署名する人だけが持つ
e = 7 # 公開鍵: 誰でも検証に使える
message_hash = 50 # 文書のハッシュ値のかわりの小さな数
signature = pow(message_hash, d, n)
print(signature)
print(pow(signature, e, n) == message_hash)
print(pow(signature, e, n) == 51)
# message_hash を60に変えて、もう一度実行しましょう。