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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Visual C++

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

Win32 API

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

暗号化

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

C++

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

Q&A

解決済

2回答

6918閲覧

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

dkyukinaga

総合スコア19

Visual C++

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

Win32 API

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

暗号化

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

C++

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

0グッド

0クリップ

投稿2016/05/05 15:53

編集2016/05/06 18:14

###前提・実現したいこと
Windowsデスクトップ用のソフトウェアをVC++で開発しております。ソフトウェア使用中に広告が表示される機能を備えてあるのですが、広告の画像とURLは実行ファイルとは別の専用のファイル(以下、広告ファイルと呼びます)に保存してあります。この広告ファイルを、定期的にインターネット上からダウンロード(ソースコード上で特定のURLを指定してあります)した新しいものと取り換えるつもりなのですが、そこでセキュリティ上の懸念があります。

###発生している問題・エラーメッセージ
万が一、サーバーが乗っ取られ、不正な広告ファイルをアップロードされてしまうと、ユーザーを危険にさらすことになってしまうのです(例えばフィッシングサイトへ誘導されたり)。そこで、暗号化に目を付けました。私だけが所有する秘密鍵で暗号化し、ソフトウェアに組み込んだ公開鍵で復号化すれば、広告ファイルの偽造は非常に困難になると考えたのです。ですが結局、いろいろ検索してみた結果、CryptoAPIで秘密鍵で暗号化し公開鍵で復号化する方法(署名を除く)を見つけることができませんでした。署名でも上記の目標は達成できると思うのですが、できればインターネット上に置くファイルはたくさんのアクセスに備えて1バイトでも小さい方がいいような気がするので、ハッシュではなくファイル本体を秘密鍵で暗号化したいと考えております。

###聞きたい事
0. CryptoAPI(またはCNG)で秘密鍵で暗号化し公開鍵で復号化する方法はありますか?自分でCSPを作る方法はなしでお願いします。
0. 秘密鍵での暗号化または署名によって、上記のような用途でユーザーの安全を確保できるといえるでしょうか?

以上、日本語や認識が怪しいところもあるかもしれませんが、ご回答いただけると幸いです。どうぞ宜しくお願いいたします。

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

聞きたいこと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/05 22:07

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dkyukinaga

2016/05/07 22:37

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

0

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

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

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

CNG:公開鍵暗号で暗号化

投稿2016/05/06 02:03

編集2016/05/06 02:05
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dkyukinaga

2016/05/06 18:18

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

2016/05/07 02:32

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

2016/05/07 03:16

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

2016/05/07 14:13

catsforepawさん > お役に立てなくて申し訳ありません。 とんでもございません。わざわざ試していただいてありがとうございます。 > 秘密鍵での暗号化は成功するものの、 暗号化に使用した関数はCryptEncryptですか?この関数には鍵ペアのハンドルを渡しますが、暗号化に使うのが公開鍵なのか秘密鍵なのか指定できず、強制的に公開鍵で暗号化されてしまうものだと思い込んでいたのですが、秘密鍵を指定する方法があるのでしょうか?教えていただけると幸いです。 ちなみに僕が試したのは、AT_SIGNATUREの鍵ペアでのCryptEncryptです。FALSEが返ってきてしまいました。 tkowさんもsharowさんもご回答、誠にありがとうございます。
catsforepaw

2016/05/07 15:22

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

2016/05/07 22:30

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問