私の安全なコンテナ

C ++でプロジェクトを開発するとき、安全なコンテナを作成することが必要になりました。 むしろ、数バイトからギガバイトまでの情報の安全な保存をサポートするソースコードレベルのクロスプラットフォームクラス。これにより、ストリーミングの暗号化/復号化をサポートする必要が生じます。

この段階でプロの暗号作成者を雇う代替手段がないため、彼は自転車の作成に着手しました。

この記事は、暗号化に近い人々による提案されたソリューションの公開討論と、時間と労力を節約するためにゼロからこの方法で進む人々のために書かれています。



情報の調査および分析中に、OpenSSLが選択されました(他のライブラリと比較して優れた速度で判断し、プロジェクト、クロスプラットフォームに組み込む際に問題は発生しませんでした)、および選択するキーとして128、192、256のAES暗号化アルゴリズム(Rijndael) (誰が知っている適切な委員会によって)最新の暗号化標準として認識されています。



最初の質問は、暗号的に安定した(擬似)乱数の生成とそのインストール(シード)です。 たとえば、暗号化キーの生成に適しています。 ジェネレーターアルゴリズムは、非常に論理的にはOpenSSLから取得されますが、シードを使用すると、問題はより複雑になります。 / dev / * randomを持つPOSIXシステムは、ランダムシードの責任を軽減します。 Windowsの場合、OpenSSLでは、一連のメッセージをウィンドウ(より良い)と画面のコンテンツ(より悪い)に送ることができます。 それにもかかわらず、ウィンドウ内のメッセージを使用したソリューションはユーザーにとって不必要な問題であるため、私はそのソリューションがあまり好きではありませんでした。 私は、画面のコピーに加えて5セントを支払いました。 それらは、Windowsによる一意のGUIDの生成を使用するという事実に基づいているため、スクリーンキャプチャの前のシードに、GetTickCount()XOR System_time XOR GUIDから少しのシフトと変換を伴うワニを追加します。

ところで、Windows XP SP2 x64での実際のテストでは、OpenSSLジェネレーターは、デフォルトで既に十分にシールされていると述べました。 理由-わかりませんが、代替案として、解決策が提案されています(追加の座席が必要なシステムで有効化されています)。



続けましょう。 したがって、キー自体が個別に格納されていると仮定すると、コンテナには復号化に必要なすべての情報が含まれている必要があります。 ストリーミング(cbc)モードのAESの場合、アルゴリズムは16バイト(128ビット)のブロックで動作するため、初期初期化ベクトル(iv0)と正確なデータ長を保存する必要があります。



初期ベクトルの保存に関しては、 RFC 3394標準がありますが、慎重に研究した結果、初期初期ベクトルの定数値を使用することが判明しました。 同時に、「暗号の紹介」という本は、初期ベクトルは決して一定であってはならないことを明確に述べています( ここ )。 したがって、暗号的に強力な乱数ジェネレーターを使用して初期化ベクトルを作成することを優先して、このアルゴリズムを放棄しました。



初期ベクトルの長さは16バイトで、データブロックの長さと同じです。



タイトルに移りましょう。 ヘッダーの長さを16バイトの倍数(AESブロックのサイズ)にするには、ベクターの長さが16バイトであることを思い出し、すべての追加データを他の16バイトに収めることをお勧めします。 サイズは8バイトでした(そう、ビッグデータ)。 残りの8バイトをマジックナンバーに割り当て、キーが正しく選択されたことをある程度保証します。 そしてここで、私は事前に用意されたマジックナンバー(M)から逃げようとしました。 私の考えはこれです:事前に準備された4バイトの定数を取ります。 2つの永続的なランダム4バイトA1およびA2を生成します。 この場合、最初の数値はそのままにして、次の条件で2番目の数値を変更します

A1 + A2 '= M


それから

A2 '= A2 + D


そして

D = M-(A1 + A2)




同時に、パスワードの正当性を判断するために、ヘッダーの最初の16バイトブロックを解読し、最初の2つのdwordを取得して、何が起こったかをまとめて確認します。 値が一致する確率は小さいですが、有限です。 私の場合、これはまったく問題ありません(キーが正しくない場合、これはすでに攻撃者が偽復号化データを受け取ったという問題です)。



データサイズを16バイトに揃えるには、必要な数のランダムバイトを末尾に追加することにより、最も簡単に行います。これにより、暗号強度の高いOpenSSLジェネレーターも作成します。



したがって、ソースデータの定数と(上記のように)定数の初期化ベクトルを取り除きます。

さらに、技術的な問題:48バイトのヘッダーIはブロックモード(ecb)でAESをエンコードし、データブロックはストリーミングモード(cbc)で暗号化されます。



画像



PS改善できる点:

+ Windows(およびPOSIX?)の初期シードをよりランダムにします

+ジェネレーターではなく、sidを使用して初期初期化ベクトルを作成します

+おそらく、データの一部と同じストリーミングモードでヘッダーを暗号化する方が良いでしょう

+キー検証の信頼性を高める

+ ...?



All Articles