質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • C++

    3635questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    229questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

  • Visual C++

    115questions

    Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

  • 暗号化

    83questions

    ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

CryptoAPI 秘密鍵で暗号化、公開鍵で復号化

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,275

dkyukinaga

score 13

前提・実現したいこと

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で秘密鍵による暗号化を実現する方法はないということなんでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

聞きたいこと1に関して
英文のやりとりで, Microsoft cryptography providersに組み込んで使うのは無理だが,CryptoAPIには暗号化,復号の関数があるというような趣旨に思えます。
署名はMCPで作成して,暗号化,復号はCAPIを使って独自の実装をしてくださいという意味だと思います。また,
RSA暗号を利用するかつCryptAPIにこだわらなければ,有名なOpenSSLというライブラリがあるので,こちらを組み込んで見るのはどうでしょう。

聞きたいこと2に関して
ファイルの暗号化だけでも有効ですが完全になりすましと改竄を検知したいのであれば平文と暗号文を両方送る必要があります。こちらの資料が分かりやすいと思います。また公開鍵認証はファイルサイズが大きいほど計算時間やデータサイズなどの,復号コストが大きくなります(圧縮アルゴリズムなどを入れれば別です)。データサイズが大きくなる理由は暗号化時に,親集合の空間(法)に飛ばし(写像し),paddingなどの処理を入れるため最低でも平文長以上のbit数が必要になるからです。時間コストはマシンスペックによって変わりますが,1024bitsのRSA暗号で大体,暗号化に66bytes/sec,復号に1kbytes/secくらいなので,普通は平文とhashを暗号化したものを両方送り,送信先で両方のhashを計算するのが無難です。計算時間が問題にならない場合はこの限りではないですが画像データとなるとかなり遅くなることが予想されます。

また,サーバを乗っ取られてしまったという状況を想定している場合ですが,この時点で基本的にあってはならないことなので,質問者様がサーバの管理者であるならば,まずこうならないように対策を講じるべきでしょう。
管理者ではないなど,なんらかの理由でそれらに対する対策が期待できないという前提でクライアントへの影響防止策として,秘密鍵で暗号化したものをuploadするという運用の仕方を想定していると思うのですが,暗号理論的には,管理しなければいけない鍵を増やすということは,新たなリスクを産むことが知られています。
サーバのアクセス権と,画像のupload鍵の入手難易度が同じ程度かそれ以上に難しくなければセキュリティ対策として,本質的な意味はなくなります。それどころかセキュリティリスクを増大させることもあります。今回の例であれば,守るべき対象がサーバの認証情報から秘密鍵に移っただけということになるので,それで実装コストに見合ったリスクヘッジになるかどうかを判断した上で実装するのがいいと思います。(サーバ側のセキュリティを全く信用できないとか干渉できないということであればこの限りではないです。実装を無意味と言っている訳ではありません。本当にもしもの時には役に立つかもしれません)

個人的にはサーバの認証情報は最も漏れてはいけない情報であると思っているので,サーバ側でせきとめる方法を考えたほうが費用対効果が高いかなと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/08 07:37

    実装コストに見合ったリスクヘッジかどうか、という視点は目から鱗です。僕はこの問題でたくさんの時間を費やし、結局一番最初に選択し得た妥協案(署名)を選ぶことにしました。プログラマーたるものソースコードの外側でも論理的に考え行動しなければなりませんね(汗)

    ご回答、誠にありがとうございました。

    キャンセル

0

英語がイマイチわからないのですが、少なくともこの記事が書かれた時点では自分でCSP作る以外にCryptoAPIで公開鍵による暗号化を実現する方法はないということなんでしょうか。

それは、そのリンク先で質問されている方のやろうとしていることが、「マイクロソフトが提供している標準のCSPではできない」ということだと思います。
単純にデータを公開鍵方式で暗号化することは、ごく一般的に行われていますので、マイクロソフトが標準で提供している機能で実現できます。

検索したらこのようなサイトが見つかりました。判りやすく書かれていると思います。

CNG:公開鍵暗号で暗号化

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/07 03:18

    ごめんなさい、誤字がありました。私の求めていたのは、公開鍵による暗号化ではなく秘密鍵による暗号化です。大変失礼いたしました。やはり、マイクロソフトが標準で提供している機能で、秘密鍵による暗号化/公開鍵による復号化は実現できないのでしょうか?

    キャンセル

  • 2016/05/07 11:32

    RSAは双方向に暗号化・復号化できるはずなので単に入れ替えれば良いと思ったのですが、試しに実行してみたところ、秘密鍵での暗号化は成功するものの、公開鍵での復号化はなぜか失敗しますね。もしかしてすでに試した上で質問されていましたか? NCrypt版も同じでしょうか。試していないので判りませんが。
    お役に立てなくて申し訳ありません。

    キャンセル

  • 2016/05/07 12:16

    > 公開鍵による暗号化ではなく秘密鍵による暗号化

    秘密鍵による暗号化は普通はsigning(署名)といいます。公開鍵、つまりみんなが復号できちゃう暗号文には意味が無いからです。逆に秘密鍵でないと作れない暗号文である、という仕組みが証明書や署名として使える理由です。

    キャンセル

  • 2016/05/07 23:13

    catsforepawさん
    > お役に立てなくて申し訳ありません。

    とんでもございません。わざわざ試していただいてありがとうございます。

    > 秘密鍵での暗号化は成功するものの、

    暗号化に使用した関数はCryptEncryptですか?この関数には鍵ペアのハンドルを渡しますが、暗号化に使うのが公開鍵なのか秘密鍵なのか指定できず、強制的に公開鍵で暗号化されてしまうものだと思い込んでいたのですが、秘密鍵を指定する方法があるのでしょうか?教えていただけると幸いです。

    ちなみに僕が試したのは、AT_SIGNATUREの鍵ペアでのCryptEncryptです。FALSEが返ってきてしまいました。

    tkowさんもsharowさんもご回答、誠にありがとうございます。

    キャンセル

  • 2016/05/08 00:22

    dkyukinaga さん

    リンク先のコードをそのまま試しただけですが、暗号化はCNGのBCryptEncryptです。鍵ペアはBCryptGenerateKeyPairで作成し、BCryptExportKeyでエクスポートしていますが、公開鍵と秘密鍵を別々にエクスポートするようになっています。同様に、それをインポートするBCryptImportKeyPairも、どちらの鍵をインポートするかを指定するようになっています。

    キャンセル

  • 2016/05/08 07:30

    catsforepawさん

    ありがとうございます。僕はCNGはまだ試していないのですが、駄目でしたか。CryptoAPIはいろいろ試してみたのですが、そもそもCryptoAPIは生のデータ(ハッシュやセッションキーではなく)をペアキーによって暗号化することを想定してないように思いました。素直に署名を使います。

    ご回答、誠にありがとうございました!

    キャンセル

関連した質問

同じタグがついた質問を見る

  • C++

    3635questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    229questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

  • Visual C++

    115questions

    Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

  • 暗号化

    83questions

    ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。