アプリ版:「スタンプのみでお礼する」機能のリリースについて

デジタル署名の仕組みについて教えてください。

デジタル署名の仕組みは、メールの内容(原文)からメッセージダイジェストを作成し、それを送信者の秘密鍵で暗号化したものを署名として原文(または暗号文)に付けるということですが、どうして単に原文そのものを暗号化したものを署名として送らないのでしょうか?

改ざん防止の為であれば、原文そのものを暗号化して送れば、受信側で改めてメッセージダイジェストを作成し、それと復号化したメッセージダイジェストを突き合わせて検証するようなことをしなくても済むと思うのですが。

いづれにしても公開鍵で復号化できるということは、秘密鍵を持っている送信者が署名した段階から改ざんされていないはずですし、その公開鍵が証明書等により検証できていれば、確かに本人であるということになりますよね。

現実世界の「署名」のように、署名とは原文とは別につけるもの(=わざわざ復号化しなくても原文が読める)、いうことに似せているだけのことでしょうか?

(参考URL)
http://www.ipa.go.jp/security/awareness/administ …

A 回答 (5件)

No.4です。

回答のお礼欄を拝見する限りご理解いただけたようですが、若干補足いたします。

回答のお礼欄に
『そう簡単に「悪意のある第三者が勝手に(m',s')を公開してしまえば...」ということはできないのでしょうが…』
とありますが、ご質問にあるメッセージ復元型の電子署名の場合で、もしm'が意味のある数字である必要がないのであれば、公開されている検証鍵と公開情報だけあれば簡単に偽造できてしまいます。というのも、現在使われている公開鍵暗号系を用いた電子署名は数値演算によって構成されており、先の回答でも書いたとおり適当な数字s'に対して、公開されている署名鍵(e,n)を使ってs'^e mod nは誰でも演算ができます。この演算結果をm'と言ってしまえば、結果的にs'はm'の署名になっているわけです。

これに対しハッシュ関数(h=Hash(m))を用いた署名の場合ですが、
署名:s=h^d mod n
検証:h=s^e mod n ⇒ if h==Hash(m) then True else False
となります。
このとき、先ほどと同様に適当な数字s'に対してはs'^e mod nは計算できますが、その後の判定を成功させるにはs'^e mod nとなるようなHash(m')を作る必要があります。しかし、ハッシュ関数が暗号学的な一方向性のものであれば、当然ハッシュ関数の逆演算はできないため、Hash(m')==s'^e mod nとなるようなm'を求めることは事実上不可能です。

一般的には
「あるメッセージに対して、署名鍵を知らない人でも署名が作れる」
ということだけを偽造と考えると思いますが、暗号学の世界では
「ある署名の値に対して、署名鍵を知らない人でもこの署名に合うようなメッセージを作れる」
という偽造に対しても安全性を担保する必要があり、そのためにハッシュ関数が使われているとなります。

もし暗号・署名の仕組みや安全性とかに興味があれば、参考URLにあるような大学の学部生向けの暗号の教科書とかもありますので、ぜひ読んでみてください。

参考URL:http://book.akahoshitakuya.com/b/4526064521
    • good
    • 0
この回答へのお礼

もし原文そのものを署名とした場合は、たとえ(偽造した署名による)検証結果=原文が意味を成さないものであれ、それ以上の検証ができないことから、「公開鍵で検証した結果なのだから本来の署名者が確かに署名したものだ!」と主張できてしまうということですね。

そして、検証結果は公開鍵により簡単に偽造できるということですね。

それならば単に原文そのものを署名とすることには問題がありますね。メッセージダイジェストによる検証が必要であると納得できます。

どこでも説明されているデジタル署名の仕組みについて素朴な疑問だったのですが、深いというか根本的なことが関わっていたのですね。

ありがとうございました。

お礼日時:2012/11/28 07:07

これより先に回答した方が指摘されていないことですが、単に原文そのものを暗号化したものを署名として送るのでは、署名の偽造ができてしまう(存在的偽造が可能である)からです。



RSA署名で考えて見ます。署名(秘密)鍵を(d,n)、検証(公開)鍵を(e,n)とします。

メッセージダイジェスト(ハッシュ関数)を使わない場合、メッセージmに対する署名は
署名:s=m^d mod n
となり、このsを公開します。検証者はこのsと検証鍵を使って
検証:m=s^e mod n ※s^e mod n=(m^d)^e mod n=m^ed mod n=m
を計算することで検証となります。

このとき、悪意のある第三者がある適当な乱数s'を用意し、
m'=s'^e mod n
を用意し、勝手に(m',s')を公開してしまえば、署名者が署名処理をしていない(s'=m'^d mod nを計算していない)にも関わらず署名者の署名ができてしまい、偽造が成功しています。

もちろん、このときのmが意味のあるメッセージになっていない可能性の方が非常に高いですが、それでも「この意味も無いメッセージに署名していない」ことは保証できません。これが「存在的偽造が可能」ということです。

メッセージダイジェストを使う理由としては、計算コスト云々よりも、このような偽造を防ぐ目的の方が(少なくとも学術的には)意味として強いです。
    • good
    • 0
この回答へのお礼

デジタル署名には「存在的偽造が可能」があるのですか!

RSA暗号では、「秘密鍵を用いずに暗号文から平文を得ることは難しい」という安全根拠があり、改ざんについては実用面ではほぼ不可能なのでしょうが、なりすましに関しては可能ということでしょうか?

まあ、そう簡単に「悪意のある第三者が勝手に(m',s')を公開してしまえば...」ということはできないのでしょうが(そう簡単であれば利用されないでしょうから)、「秘密鍵を用いずに暗号文から平文を得ること」よりは簡単にできるという程度のものなのでしょうか。

その脆弱性を補うために、受信側でも原文からメッセージダイジェストを別途作成して検証するわけですね。

ネットで調べる内容では、とてもここまでのことは説明されていないので、大変勉強になりました。

ありがとうございました。

お礼日時:2012/11/27 17:24

ざくっと言えば、容量と計算時間が無駄ですし、頑張ってその方式でやっても実用されるような平文に対して暗号化されたデータが署名の意味を持たないからでしょうね。

ちょっと頑張ってその方式でやる方法を考えてみますが、公開鍵暗号で平文全体を暗号化する方法も、分割する方法もうまくいきません。前者は現実的な計算時間ではできませんし、後者は改ざんに対して脆弱です。

公開鍵暗号で暗号化できるデータの最大サイズは、例えばRSAだと鍵の長さ (素数p, qの積) までです。大きなデータを暗号化するにはそれだけ長い鍵が必要になります。例えば、1MBのデータを暗号化するには8,388,608bit以上の鍵が必要となりますが、これから送るデータがどれくらいのサイズになるのかはわからないので、これから送るかもしれないだけの異常に長い鍵を用意する必要があります。また、公開鍵暗号の場合、誰かがその鍵が正しいことを保証しないと無意味ですが、その裏付けのために長い鍵が必要になります。認証局の公開鍵は信頼出来る公開鍵としてブラウザなどに予め組み込まれるようになっていますが、こんな世界だと認証局は何ビットの公開鍵を配ったら良いのでしょうか。
http://ja.wikipedia.org/wiki/RSA%E6%9A%97%E5%8F%B7

また、公開鍵には計算時間についても欠点があります。一般に使われているコンピュータが一度に計算できるデータの大きさは公開鍵暗号の計算に必要な大きさに比べてずっと小さいです。これを実現するためにソフトウェアで計算をする必要がありますが、それにはそれなりに時間がかかります。また、公開鍵暗号としてよく使われるRSAは掛け算をeやdの回数繰り返すので、さらに時間がかかります。卑近な例で例えると、1桁同士の掛け算がハードウェアで出来る計算でそれ以上の桁数の計算がソフトウェアで計算するところだと考えるとわかりやすいかもしれません。掛け算するときは1桁の計算は九九などで暗記しているので一発ででますが、それ以上の計算は一桁ずつやって足し合わせますよね。RSA暗号での処理もそんな処理をしているので桁数が増えれば必然的に時間がかかるようになります。

というわけで、平文を公開鍵暗号で一発で暗号化するのは現実的ではありません。それでは、分割する方法はどうでしょうか?

データを例えば2048bitずつに分割すると、長いデータでも楽に暗号化できますが、この場合は改ざんに弱いという問題が出てきます。暗号文を攻撃する方法としてよくある方法に、暗号文の順序を入れ替えるという方法があります。分割する場合はこれに対処できる必要がありますが、平文と暗号文とを対応させて順番を入れ替えると改ざんされたことを見つけることは不可能です。
そもそも電子署名を使わずに暗号化したデータを署名付きデータと思って送る場合も同じです。暗号化したデータを送り、メッセージダイジェストがない場合、順序の入れ替えがないことを示すのは不可能です。
これに対抗するために、通し番号を振る方法を考えると、効率と安全性のトレードオフになるのであまりやりたくないと思います。効率を考えて8bitの通し番号にすると256ブロック単位での入れ替えには脆弱ですし、64bitの通し番号をつけると8バイトはデータではないものを毎回送ることになるので無駄が多いですしね。

と、ここまでの問題はすべて平文と同じ長さの暗号文を送ろうとしたから起きた問題です。これが平文のメッセージダイジェストを送るようにしていたらどう変るでしょうか。

メッセージダイジェストの値は普通128bitから512bitくらいなので、1024bitの鍵を使ったRSAで一発で暗号化でき、分割の必要はありません。また、通常は鍵長より短いデータはpaddingされますが、RSAで暗号化された後のデータも鍵長より長くならないので、1024bit程度でしょう。これは、1MBのデータを送るのに1MBのデータをつけていたのとは明らかに必要な容量が減っています。

つまり、メッセージダイジェストを使った方が明らかに送信するデータは少なくなっていて、同じ効果が得られます。それだけでもメッセージダイジェストを暗号化した方が良いと言えるでしょう。


というわけで、あえて電子署名を使わないという方法を考えると非常に効率が悪いか、脆弱性があるかのどちらかの方法しかないので電子署名を使っているんだと思います。
    • good
    • 0
この回答へのお礼

やはり、本文を公開鍵暗号方式でまるごと暗号化してしまうと、(平文のデータ量次第で)処理に負荷がかかってしまい、実用的ではないのですね。

「公開鍵暗号で暗号化できるデータの最大サイズ」というものがあるのですね。どんなデータも同じく暗号化できるものだと思っていました。それならば、本文は暗号化に使用できないというのに納得がいきます。それで一定長のメッセージダイジェストを利用するのですね。大変勉強になりました。

ありがとうございました。

お礼日時:2012/11/27 16:49

あ、そうそう。

その大前提として「公開鍵による復号化処理は
メチャメチャ重い」ってコトもあります。

全文を暗号化すると、復号に手間がかかって仕方ありません。
ですので、ハッシュ値を暗号化することで、復号処理を軽量化
してるんです。

同じように、VPN通信でも「共通鍵を公開鍵で送り、本文は
共通鍵で暗号化」なんて面倒なことをしますよね。これも
「公開鍵による復号化はメチャメチャ手間がかかる」ためで、
共通鍵を送る程度なら何とかなる・・・ってのが前提にあります。
    • good
    • 0
この回答へのお礼

なるほど、復号化処理の負荷が無駄に大きくなってしまうのですね。
ありがとうございました。

お礼日時:2012/11/27 16:36

一番大きな理由は、「暗号化したい文書では無いから」です。



デジタル署名付きの文書は、文書そのものを誰にでも公開
したいんですね。ですので、本文は暗号化できない。

でも、暗号化せず本文を公開すると、文書を改ざんされても
判断が付かないんです。「誰にでも見てほしい」「でも本文は
改ざんされたくない」という時に使うのが「デジタル署名」なん
ですね。

デジタル署名が正しく復号出来るなら、その文書は改ざん
されていない、復号できないなら怪しい・・・ってことですから
「リアル」での「サイン」と意味は全く同じです。

内容も秘密にしたい場合は、デジタル署名と暗号化を同時に
する・・・なんてこともしますよ。

この回答への補足

「誰にでも見てほしい」「でも本文は改ざんされたくない」だとしても、本文を暗号化したものを復号化してもらえばよいのでは? と思いました。デジタル署名としても復号化するわけですから。

補足日時:2012/11/27 16:30
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!