質問: ### 前提・実現したいこと Windowsデスクトップ用のソフトウェアをVC++で開発しております。ソフトウェア使用中に広告が表示される機能を備えてあるのですが、広告の画像とURLは実行ファイルとは別の専用のファイル(以下、広告ファイルと呼びます)に保存してあります。この広告ファイルを、定期的にインターネット上からダウンロード(ソースコード上で特定のURLを指定してあります)した新しいものと取り換えるつもりなのですが、そこでセキュリティ上の懸念があります。 ### 発生している問題・エラーメッセージ 万が一、サーバーが乗っ取られ、不正な広告ファイルをアップロードされてしまうと、ユーザーを危険にさらすことになってしまうのです(例えばフィッシングサイトへ誘導されたり)。そこで、暗号化に目を付けました。私だけが所有する秘密鍵で暗号化し、ソフトウェアに組み込んだ公開鍵で復号化すれば、広告ファイルの偽造は非常に困難になると考えたのです。ですが結局、いろいろ検索してみた結果、CryptoAPIで秘密鍵で暗号化し公開鍵で復号化する方法(署名を除く)を見つけることができませんでした。署名でも上記の目標は達成できると思うのですが、できればインターネット上に置くファイルはたくさんのアクセスに備えて1バイトでも小さい方がいいような気がするので、ハッシュではなくファイル本体を秘密鍵で暗号化したいと考えております。 ### 聞きたい事 1. CryptoAPI(またはCNG)で秘密鍵で暗号化し公開鍵で復号化する方法はありますか?自分でCSPを作る方法はなしでお願いします。 2. 秘密鍵での暗号化または署名によって、上記のような用途でユーザーの安全を確保できるといえるでしょうか? 以上、日本語や認識が怪しいところもあるかもしれませんが、ご回答いただけると幸いです。どうぞ宜しくお願いいたします。 ### 試したこと 「CryptoAPI 秘密鍵で暗号化」などと検索しても、普通の鍵交換や署名の方法ばかり出てきて、ほとんどこの話題に関する記事を見つけることができませんでした。そんな中でもこのようなやり取りを見つけました。 その中に以下のような記述があります。 > > > decrypting with public key. I guess by that it is not possible with cryptoapi ? > > > It is possible with CAPI, but not possible with any of standard Microsoft > > cryptography providers (not current version at least). But nothing stops you > > from developing your own cryptography provider, signing it (by Microsoft) > > and using it from your programs. > > > 英語がイマイチわからないのですが、少なくともこの記事が書かれた時点では自分でCSP作る以外にCryptoAPIで秘密鍵による暗号化を実現する方法はないということなんでしょうか。
回答: 聞きたいこと1に関して 英文のやりとりで, Microsoft cryptography providersに組み込んで使うのは無理だが,CryptoAPIには暗号化,復号の関数があるというような趣旨に思えます。 署名はMCPで作成して,暗号化,復号はCAPIを使って独自の実装をしてくださいという意味だと思います。また, RSA暗号を利用するかつCryptAPIにこだわらなければ,有名なOpenSSLというライブラリがあるので,こちらを組み込んで見るのはどうでしょう。 聞きたいこと2に関して ファイルの暗号化だけでも有効ですが完全になりすましと改竄を検知したいのであれば平文と暗号文を両方送る必要があります。こちらの資料が分かりやすいと思います。また公開鍵認証はファイルサイズが大きいほど計算時間やデータサイズなどの,復号コストが大きくなります(圧縮アルゴリズムなどを入れれば別です)。データサイズが大きくなる理由は暗号化時に,親集合の空間(法)に飛ばし(写像し),paddingなどの処理を入れるため最低でも平文長以上のbit数が必要になるからです。時間コストはマシンスペックによって変わりますが,1024bitsのRSA暗号で大体,暗号化に66bytes/sec,復号に1kbytes/secくらいなので,普通は平文とhashを暗号化したものを両方送り,送信先で両方のhashを計算するのが無難です。計算時間が問題にならない場合はこの限りではないですが画像データとなるとかなり遅くなることが予想されます。 また,サーバを乗っ取られてしまったという状況を想定している場合ですが,この時点で基本的にあってはならないことなので,質問者様がサーバの管理者であるならば,まずこうならないように対策を講じるべきでしょう。 管理者ではないなど,なんらかの理由でそれらに対する対策が期待できないという前提でクライアントへの影響防止策として,秘密鍵で暗号化したものをuploadするという運用の仕方を想定していると思うのですが,暗号理論的には,管理しなければいけない鍵を増やすということは,新たなリスクを産むことが知られています。 サーバのアクセス権と,画像のupload鍵の入手難易度が同じ程度かそれ以上に難しくなければセキュリティ対策として,本質的な意味はなくなります。それどころかセキュリティリスクを増大させることもあります。今回の例であれば,守るべき対象がサーバの認証情報から秘密鍵に移っただけということになるので,それで実装コストに見合ったリスクヘッジになるかどうかを判断した上で実装するのがいいと思います。(サーバ側のセキュリティを全く信用できないとか干渉できないということであればこの限りではないです。実装を無意味と言っている訳ではありません。本当にもしもの時には役に立つかもしれません) 個人的にはサーバの認証情報は最も漏れてはいけない情報であると思っているので,サーバ側でせきとめる方法を考えたほうが費用対効果が高いかなと思います。