私は常に、コードへのアップグレードが信頼できるソースから来たものであることを確認するために、アセンブリに署名する目的をランタイムチェックと理解しています。実際には、この種のシナリオを避けようとしています。
私はA社から暗号化ライブラリを購入しました。その後、B社はメールの詳細を取得し、大きなセキュリティ上のバグであると思われるアセンブリへの無料アップグレードを私に送ります会社Bのサーバーに暗号化しようとしていたすべてのデータを送信する隠しメソッドを実際に自分のコードに挿入すると、会社Aから修正されます。私がばかだと仮定すると、盲目的に私のアプリケーションのbinディレクトリに盲目的にこれを追加すると、これは古いバージョンと同じ秘密鍵で署名されていないという事実が、実行時に検出され、例外が発生し、データを保護します。
したがって、元のファイルが特定のベンダーのものであることを保証するものではないため、アセンブリの外に公開鍵を公開する理由はなく、すべての後続バージョンは最初。
Wikipediaは、ほとんど同じことを言います(単語数が大幅に少ない)。
これをより明確にするための試みで、さらに情報を追加するために編集...
私が最初に明確にする必要がありますものは、公開鍵と秘密鍵のペアが一意であることだと思います。つまり、同じハッシュチェックをパスするような方法でアセンブリを再構築するには、公開鍵を知っているだけでは十分ではありません。
そのため、ユーザーBはアプリケーションBのフォルダにあるA社の暗号化ライブラリを使用しています。この次のように彼はDLLを参照している行うには:
Encryption, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07"
を公開鍵の目的は、私は一度に一つを処理しますthree benefitsをご提供することです。
最初に、それはアセンブリの一意の名前を提供します。これによりセキュリティは強化されますが、Encyptionバージョン1.0.0.0と呼ばれる2つの異なるライブラリをリリースできるCスタイルdll Hellは停止します。それらを区別する方法がないので、それらを同じディレクトリに格納する必要があります。
第2に、私の元の投稿で概説したシナリオを妨げます。 B社にとって、バージョン1.0.0.0であり、同じ公開鍵を持つ別のバージョンの暗号化ライブラリを作成することは不可能です(名前全体が一致し、A社の代わりにコードを呼び出すことになります)。公開鍵が一致した場合、秘密鍵も一致する必要があります(それぞれのペアが一意であるため)。秘密鍵を取得して一致させる唯一の方法は、A社のセキュリティを侵害することです。
最後に、ファイルの完全性が保証されます(破損または悪意のあるコードの挿入によって変更される)。 dllは実行時に(プライベートでアプリケーションのbinフォルダに)ハッシュされるか、または公開鍵を使用してインストール時(GACに入れたとき)にハッシュされ、そのハッシュは非公開で暗号化されたハッシュと比較されますキーを押してアセンブリに格納します。 This pageにはいくつかの図や詳細があります。このハッシュを偽造する唯一の方法は、秘密鍵を知ることです。
上記の特定のシナリオをカバーするには、ユーザーBに暗号化DLLの悪意のあるバージョンを提供しようとしているB社のふりをします。私の最初の試みは、暗号化とバージョン1.0.0.0の名前で自分のdllを作成して、自分の鍵ペアで署名することです。残念ながら、ユーザーZのアプリケーションで参照コードを変更できないため、フルネームチェックに失敗して読み込まれません。 「大丈夫です」と私の口ひげを振り回しながら私は言う。「私は単に私の議会の公開鍵をA社の公開鍵に変更するだけだ。これを実行すると、名前のチェックは合格しますが、ユーザーZのアプリケーションは、パブリックキー(会社Bの秘密キーで暗号化された)で保存されたハッシュを解読できないため、ハッシュチェックは失敗しますA's)が提供されています。したがって、企業Bが企業Aのように見える図書館を作成する唯一の方法は、企業Aの秘密鍵を知ることです。これらのセキュリティチェックのどれも、A社が公開鍵を他の場所に公開することに依存していませんが、アセンブリの元のリリースにあります。
元のアセンブリがA社のもので、VerisignやMicrosoftのAuthenticodeなどの他のシステムで処理されていることを保証するものではなく(保証するものではありません)一度アセンブリを参照すると、A社のみがそのコードを変更することができます。
これは完全にはっきりしておらず、リンクされた記事で明示的に言及されていません。このすべてを実行するためには、ランタイムは、各アセンブリのハッシュをキャッシュし、アセンブリをロードするときにそれを確認する必要があります。それは本当にこれをしますか? – sharptooth
Jeffery Richterの "CLR via C#"によれば、アセンブリがGACにないときに実行されます。 「強力な名前のアセンブリをGAC以外の場所からロードすると、CLRはアセンブリがロードされるときにハッシュ値を比較します。つまり、アプリケーションが実行され、アセンブリをロードするたびにファイルのハッシュが実行されますこのパフォーマンスヒットは、アセンブリファイルの内容が改ざんされていないことを確実にするためのトレードオフです。 –
私はこの引用符を「C#via CLR」から追加します(途中でおすすめの本):重要:このメカニズムは、ファイルの内容が改ざんされていないことを保証します。パブリッシャーがあなたの公開鍵を作成し、パブリッシャーの秘密鍵が決して妥協されなかったと確信しているということが絶対に肯定的でない限り、パブリッシャーの誰かを教えてください。したがって、パブリックキーをアセンブリとは別にパブリッシュしても、依然としてパブリッシャを確認することはできません。 –