公開鍵はどのようにして署名を検証するのですか?


173

私は公開鍵/秘密鍵がどのように機能するかについてより良い取り組みをするために努力しています。送信者が自分の秘密鍵を使用してドキュメントにデジタル署名を追加し、基本的にドキュメントのハッシュを取得する場合があることを理解していますが、公開鍵を使用してその署名を検証する方法がわかりません。

私の理解は、公開鍵は暗号化し、秘密鍵は復号化するということでした...誰かが私を理解するのを助けることができますか?


3
いい質問だ。:)
スラジュジャイン

私はこれを答えとして追加したくなく、続く炎の危険を冒したくありませんでしたが、「どのように」という言葉が本当に「どのようにして署名を検証するのか」を意味する場合、1つの可能性はgpg4winをダウンロードすることです。インストールしたら、ファイルを右クリックして確認できます。これは、Windowsシェルに統合される製品のスイートです。そのようなユーティリティの1つは、証明書をオンラインで検索して検証を行うKleopatraです。
Newclique

回答:


210

「公開鍵の暗号化、秘密鍵の復号」についてのあなたの理解は正しいです...データ/メッセージの暗号化について。デジタル署名の場合は、その逆です。デジタル署名を使用すると、自分が署名したドキュメントが自分からのものであることを証明しようとしています。そのためには、自分だけが持っているもの、つまり秘密鍵を使用する必要があります。

最も簡単な説明のデジタル署名は、データ(ファイル、メッセージなど)のハッシュ(SHA1、MD5など)であり、その後、署名者の秘密鍵で暗号化されます。それは署名者だけが持っている(または持っているべき)ものなので、そこから信頼が生まれます。誰もが署名者の公開鍵にアクセスできます(または持つ必要があります)。

したがって、デジタル署名を検証するために、受信者は

  1. 同じデータ(ファイル、メッセージなど)のハッシュを計算します。
  2. 送信者のPUBLICキーを使用してデジタル署名を復号化します。
  3. 2つのハッシュ値を比較します。

それらが一致する場合、署名は有効と見なされます。それらが一致しない場合は、別のキーを使用して署名したか、データが(意図的または非意図的に)変更されていることを意味します。

お役に立てば幸いです。


13
私の理解では、キーは対称的ではありませんでした...つまり、公開キーで暗号化されたオブジェクトは秘密キーで復号化できますが、この関係は逆に機能しませんでした...具体的には、オブジェクトとは思わなかった秘密鍵で暗号化すると、公開鍵で復号化できます。それが本当にそうである場合、これは間違いなく私の質問に答えます。
jcampos8782 2013

63
キーは互いに逆の働きをします。あなたの公開鍵で何かを暗号化しましたか?秘密鍵で暗号化を解除します。逆に、秘密鍵で何かを暗号化した場合は、公開鍵で復号化します。これが非対称暗号の性質です。
シャドウマン2013

20
対称とは、暗号化/復号化に同じキーが使用されることを意味します。非対称とは、1つのキーが暗号化し、別のキーが復号化することを意味します(逆も当てはまります)。
gtrig 2013

8
@ジョディモロ、技術的には、秘密鍵で暗号化されているメッセージは「秘密」ではありません。秘密鍵で暗号化されている場合、公開されている「公開」鍵を持っている人なら誰でもメッセージを復号化できます。
RayLoveless、2018年

4
@Jodimoroハッシュが秘密キーで署名に暗号化される唯一の理由は、ハッシュが変更されないようにすることです...それが「秘密」であることを保証することではありません。
RayLoveless、2018年

72

キーは逆に機能します:

公開鍵による暗号化、秘密鍵による復号化(暗号化):

openssl rsautl -encrypt -inkey public.pem -pubin -in message.txt -out message.ssl
openssl rsautl -decrypt -inkey private.pem       -in message.ssl -out message.txt

秘密鍵の暗号化、公開鍵の復号化(署名):

openssl rsautl -sign -inkey private.pem       -in message.txt -out message.ssl
openssl rsautl       -inkey public.pem -pubin -in message.ssl -out message.txt

以下は、このフロー全体をでテストするスクリプトの例opensslです。

#!/bin/sh
# Create message to be encrypted
echo "Creating message file"
echo "---------------------"
echo "My secret message" > message.txt
echo "done\n"

# Create asymmetric keypair
echo "Creating asymmetric key pair"
echo "----------------------------"
openssl genrsa -out private.pem 1024
openssl rsa -in private.pem -out public.pem -pubout
echo "done\n"

# Encrypt with public & decrypt with private
echo "Public key encrypts and private key decrypts"
echo "--------------------------------------------"
openssl rsautl -encrypt -inkey public.pem -pubin -in message.txt         -out message_enc_pub.ssl
openssl rsautl -decrypt -inkey private.pem       -in message_enc_pub.ssl -out message_pub.txt
xxd message_enc_pub.ssl # Print the binary contents of the encrypted message
cat message_pub.txt # Print the decrypted message
echo "done\n"

# Encrypt with private & decrypt with public
echo "Private key encrypts and public key decrypts"
echo "--------------------------------------------"
openssl rsautl -sign    -inkey private.pem -in message.txt          -out message_enc_priv.ssl
openssl rsautl -inkey public.pem -pubin    -in message_enc_priv.ssl -out message_priv.txt
xxd message_enc_priv.ssl
cat message_priv.txt
echo "done\n"

このスクリプトは以下を出力します。

Creating message file
---------------------
done

Creating asymmetric key pair
----------------------------
Generating RSA private key, 1024 bit long modulus
...........++++++
....++++++
e is 65537 (0x10001)
writing RSA key
done

Public key encrypts and private key decrypts
--------------------------------------------
00000000: 31c0 f70d 7ed2 088d 9675 801c fb9b 4f95  1...~....u....O.
00000010: c936 8cd0 0cc4 9159 33c4 9625 d752 5b77  .6.....Y3..%.R[w
00000020: 5bfc 988d 19fe d790 b633 191f 50cf 1bf7  [........3..P...
00000030: 34c0 7788 efa2 4967 848f 99e2 a442 91b9  4.w...Ig.....B..
00000040: 5fc7 6c79 40ea d0bc 6cd4 3c9a 488e 9913  _.ly@...l.<.H...
00000050: 387f f7d6 b8e6 5eba 0771 371c c4f0 8c7f  8.....^..q7.....
00000060: 8c87 39a9 0c4c 22ab 13ed c117 c718 92e6  ..9..L".........
00000070: 3d5b 8534 7187 cc2d 2f94 0743 1fcb d890  =[.4q..-/..C....
My secret message
done

Private key encrypts and public key decrypts
--------------------------------------------
00000000: 6955 cdd0 66e4 3696 76e1 a328 ac67 4ca3  iU..f.6.v..(.gL.
00000010: d6bb 5896 b6fe 68f1 55f1 437a 831c fee9  ..X...h.U.Cz....
00000020: 133a a7e9 005b 3fc5 88f7 5210 cdbb 2cba  .:...[?...R...,.
00000030: 29f1 d52d 3131 a88b 78e5 333e 90cf 3531  )..-11..x.3>..51
00000040: 08c3 3df8 b76e 41f2 a84a c7fb 0c5b c3b2  ..=..nA..J...[..
00000050: 9d3b ed4a b6ad 89bc 9ebc 9154 da48 6f2d  .;.J.......T.Ho-
00000060: 5d8e b686 635f b6a4 8774 a621 5558 7172  ]...c_...t.!UXqr
00000070: fbd3 0c35 df0f 6a16 aa84 f5da 5d5e 5336  ...5..j.....]^S6
My secret message
done

2
スクリプトを追加していただきありがとうございます。物事を明確にするのに役立ちました。
Pat

おかげで、私は簡単に理解できるようになりました
Simon

16

公開鍵は暗号化し、秘密鍵だけが暗号化を解除できます。逆も同様です。どちらも異なるハッシュに暗号化しますが、各キーは他方の暗号化を解読できます。

メッセージが予想される送信者から送信されたことを確認するには、いくつかの方法があります。例えば:

送信者は送信します:

  1. メッセージ

  2. 秘密鍵で暗号化されたメッセージのハッシュ

受信機:

  1. 署名(2)を公開鍵で復号化してメッセージを取得します。メッセージはおそらく(1)と同じですが、まだわかりません。これで、2つのメッセージが同一であることを確認する必要があります。これを行うには、両方を公開鍵で暗号化し、2つのハッシュを比較します。だから私たちは...
  2. 元のメッセージ(1)を公開鍵で暗号化してハッシュを取得する
  3. 復号化されたメッセージを暗号化して(3)2番目のハッシュを取得し、(4)と比較してそれらが同一であることを確認します。

それらが同一でない場合は、メッセージが改ざんされたか、他の鍵で署名されていて、私たちが思ったものではないことを意味します...

もう1つの例は、送信者が、受信者も使用することがわかっている共通のハッシュを使用することです。例えば:

送信者は送信します:

  1. メッセージ
  2. メッセージの既知のハッシュを取得し、そのハッシュを秘密鍵で暗号化します

受信機:

  1. 復号化して(2)ハッシュ値を取得します
  2. 送信者が使用したのと同じハッシュでメッセージ(1)をハッシュする
  3. 2つのハッシュを比較して、それらが一致することを確認します

これにより、メッセージが改ざんされておらず、予期された送信者からのものであることが保証されます。


6

私が理解した方法からあなたの質問を言い換えなければならない場合、あなたは次のことを尋ねています:

公開鍵暗号化により、公開鍵秘密鍵から導出できるが、秘密鍵公開鍵から導出できないことが保証されている場合、公開鍵送信者なしで秘密鍵で署名されたメッセージをどのように復号化できるのか不思議に思うかもしれません署名付きメッセージ内の秘密鍵を受信者に公開しますか?(それが理にかなっているまでそれを数回読み直してください)

他の回答は、非対称暗号があなたが次のいずれかを行うことができることをどのように意味するかをすでに説明しています

  1. 公開鍵で暗号化、一致する秘密鍵で復号化(以下の疑似コード)
var msg = 'secret message';

var encryptedMessage = encrypt(pub_key, msg);

var decryptedMessage = decrypt(priv_key, encryptedMessage);

print(msg == decryptedMessage == 'secret message'); // True
  1. 秘密鍵で暗号化、一致する公開鍵で復号化(以下の疑似コード)
var msg = 'secret message';

var encryptedMessage = encrypt(priv_key, msg);

var decryptedMessage = decrypt(pub_key, encryptedMessage); // HOW DOES THIS WORK???

print(msg == decryptedMessage == 'secret message'); // True

私たちは知っている例#1と#2の仕事の両方こと。例#1は直感的に理解できますが、例#2は元の質問をします。

結局、楕円曲線暗号(「楕円曲線乗算」とも呼ばれます)が元の質問に対する答えです。楕円曲線暗号は、以下の条件を可能にする数学的関係です。

  1. 公開鍵秘密鍵から数学的に生成できます
  2. 秘密鍵、公開鍵から数学的に生成することはできません(つまり、「トラップドア機能」)
  3. 秘密鍵ができることが確認された公開鍵で

ほとんどの場合、条件#1と#2は理にかなっていますが、#3はどうですか?

ここでは2つの選択肢があります。

  1. あなたはウサギの穴を下りて、楕円曲線暗号がどのように機能するかを学ぶのに何時間も費やすことができます(ここは素晴らしい出発点です)...または...
  2. 上記のプロパティを受け入れることができます。自分で導出する必要なく、ニュートンの3つの運動法則を受け入れるのと同じです。

結論として、公開鍵と秘密鍵のペアは、楕円曲線暗号を使用して作成されます。これは、本来、双方向で数学的にリンクされているが、双方向では数学的に導出されていない公開鍵と秘密鍵を作成します。これにより、誰かが自分の秘密鍵を公開することなく、誰かが自分の公開鍵を使用して特定のメッセージに署名したことを確認できます。


あなたの3つの条件がそれをすべて説明しています。私はこの用語「楕円曲線」を読んだばかりで、私はwtfのようでした
サイモン

5

より直感的に明らかになるものを探している人には補足説明を提供すると思います。

この混乱の大部分は、「公開鍵」と「秘密鍵」に名前を付けることから生じます。これは、これらのものが実際にどのように機能するかは、「鍵」がどのように理解されるかと直接対立するためです。

暗号化を例にとってみましょう。それは次のように機能していると考えることができます:

  • 秘密のメッセージを読むことができるようにしたい当事者はそれぞれ、隠された鍵(すなわち秘密鍵)を保持します
  • 秘密のメッセージを送信できるようにしたいすべての当事者は、ロック解除されたロック(つまり、パブリックロック)を取得することができます。
  • その後、秘密のメッセージの送信は、ロック解除されたロックでロックするのと同じくらい簡単ですが、その後のロック解除は、非表示のキーの1つでのみ実行できます。

これにより、秘密のメッセージを当事者間で送信できますが、ここでは直感的な観点から、「公開鍵」より「公開鍵」の方が適切な名前です。

ただし、デジタル署名を送信する場合、役割は多少逆​​になります。

  • メッセージに署名したい当事者は、ロック解除されたロック(つまり、プライベートロック)にアクセスできる唯一の当事者です。
  • 署名を検証したいすべての当事者は、鍵(つまり、公開鍵)を取得することができます。
  • 次に、署名者が行うことは、2つの同一のメッセージを作成することです。1つは誰でも読むことができるメッセージと、それに付随するメッセージですが、プライベートロックの1つでロックします。
  • 次に、受信者がメッセージを受信すると、メッセージを読み取り、公開鍵を使用してロックされたメッセージのロックを解除し、2つのメッセージを比較します。メッセージが同じである場合、彼らはそれを知っています:

    1. ロック解除されたメッセージは、旅行中に改ざんされず、

    2. メッセージは、公開鍵に一致するロックを持っている人からのものである必要があります。

  • そして最後に、このシステム全体が機能するのは、署名者の署名を検証したい人が、署名者のロックに一致するキーを取得するための信頼できる場所にいる場合のみです。それ以外の場合、誰でも「ねえ、これがまあまあのプライベートロックの鍵です」と言って、自分になりすましてメッセージを送るが、プライベートロックでロックする場合は、上記のすべての手順を実行し、メッセージが実際にあなたが思った人からですが、あなたは公開鍵の真の所有者について誤解を招いたのでだまされています。

署名者の公開鍵を取得するための信頼できるソースがある限り、公開鍵の正当な所有者が誰であるかがわかり、署名を検証できます。


4
「キー」を「ロック解除ロック」に変更すると、混乱が増すだけです。
ローンズオブローン

@EJPキーを「ロック解除ロック」に変更しません。「ロック」に変更されました。「ロック解除されたロック」は、アイテムの使用を表す目的でのみ使用されます。よろしくお願いします。それはあなたの意見であり、暗号コミュニティで長期間の経験がある場合は、既存の用語がテクノロジーを理解するために成長した方法であるため、非常に偏っている可能性があります。例え始めたばかりの人に、類推が役立つかどうかを判断させてみませんか?

1
ロックとキーの類推は、この問題を最初に理解するには非常に良いと思います。ロックとキーを視覚化したら、rsa(または他のタイプの)キーにアセンブルされた異なる整数を交換できます。
Andreas Lundgren、2018年

私は個人的に、この洞察は最高のものだと思います。これまで読んだことがあります。また、キーの代わりにロックをプライベート/パブリックに追加すると、システム全体が定期的に新規参入者に直感的にわかりやすくなることを間違いなく確認してください。現時点ではそうではありません。私たちは経験豊かな開発者であり(今まで暗号に直接触れていないだけです)、しばらくの間、パブリック/プライベートの目的について議論しました。私は暗号化にプライベートが使用されていると言っていましたが、パブリックは暗号化に使用されていると彼は言っていました:D
jayarjo

0

あなたの質問に-私はRSAの実装を見ていました。また、公開鍵を使用して秘密鍵を使用して署名を検証する方法がより明確になりました。間違いなく、秘密鍵は公開されていません。ここに方法があります...

ここでの秘訣は、関数内で秘密鍵を非表示にすることです。この場合、(p-1)*(q-1).

pを秘密鍵、eを公開鍵と見なします。「p」は、それを非表示にするために別の関数内にカプセル化されます。

E.g., `d = (p-1)(q-1); d * e = 1` (d is the inverse of e - public key)

送信されたデータ= [暗号化(ハッシュ)、メッセージ] = [m ^ d、メッセージ]; ここで、mはメッセージです。 '送信されたデータ' = yと仮定します。整合性をチェックするには、mを取得するためにy ^ eを見つけます。以来m ^(d*e) = m ^1 = m

お役に立てれば!:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.