13

バックグラウンド

私は静的なWebコンテンツのユーザーのために動的な認証スキームの開発を可能にするシステムを設計しています。動機は、大量の複雑でありながら機密性の高いWebコンテンツを事前に生成し、Webサーバーによって強制されるCookieベースの(可逆的に暗号化された情報を埋め込む)認証を使用して静的に提供することです。AEADモードの暗号化プリミティブを使用します。

問題

一定期間、たとえば1週間(現在有効なペア)有効なIVECとキーを生成する必要があります。また、過去のIVEC /キーもたとえば2週間有効(履歴的に有効)であり、履歴的に有効なシークレットで暗号化されたデータは、現在有効なIVEC/KEYで再暗号化されます。

私が必要としているのは、乱数とパスフレーズのシードであり、64ビットまたは128ビットの数値ブロックをインデックス付きで生成できる決定論的CSPRNGです。架空のCSPRNGのインデックス要素の1つとして「1970年1月1日」から数週間を使用すると、時間の経過とともにキーを自動的に変更するシステムを構築できるはずです。

私が検討しているアプローチ

現在、cryptoppにはそのような機能が見当たらないか、用語を十分に理解しています。cryptoppは暗号化ライブラリの中で最も先進的であるため、別の暗号化ライブラリを見つける自信がありません。したがって、実装が見つからない場合は、自分で実装する必要があります。連結されたデータから静的な文字列構造を生成し、それをハッシュ(以下に表示)することでうまくいきますか?

RIPEMD160(RandomPreGeneratedFixedNonce:PassPhrase:UInt64SinceEpoch:128BitBlockIndexNumber);

注:ブロック番号は割り当てられ、通常の構造になります。たとえば、128ビットダイジェストの場合、ブロック0の最初の64ビットはivec用になり、要素1のすべては128ビットキー用になります。

これは適切なアプローチですか(つまり、暗号的に安全ですか)?

-編集:コメントを受け入れる投稿-

少し考えた後、私は最初にパスフレーズとナンス/ソルトと考えていたものを16バイト(クリプトグラフィックオールストロング)キーにマージし、PKCS#5で概説されている手法を使用して複数の時間ベースのキーを導出することにしました。パスフレーズは使用されていないため、塩は必要ありません。

4

2 に答える 2

5

興味深い質問です。

まず、初期ベクトルは暗号的に強いランダムな量である必要はありませんが、メッセージごとに一意である必要があります。IVは、実際には一種のソルト値であり、同じキーを使用して暗号化された類似のメッセージが、暗号化された後は類似していないことを保証します。任意の高速疑似ランダムジェネレーターを使用してIVを生成し、暗号化されたデータと一緒に送信(できれば暗号化)することができます。

もちろん、キーは実際に作成できる限り強力である必要があります。

ナンス、パスフレーズ、および有効性のデータを含むテキスト文字列をハッシュするというあなたの提案は、私には非常に合理的であるように思われます。これは、パスフレーズを使用してキーを生成する他のシステムによって行われることとほぼ一致しています。キーの生成を計算コストの高いものにするために、1回だけでなく、何度もハッシュする必要があります(これは、キーをブルートフォースしようとする人にとっては、自分よりも大きな問題になります)。

また、cryptoppにPasswordBasedKeyDerivationFunctionとして実装されているPKCS#5(http://www.faqs.org/rfcs/rfc2898.htmlなど)で設定されているキー生成スキームも確認することをお勧めします。このメカニズムはすでに広く使用されており、合理的に安全であることが知られています(PKCS#5ではパスフレーズデータを少なくとも1000回ハッシュすることを推奨しています)。有効期間とインデックスデータをパスフレーズに追加し、そのままPasswordBasedKeyDerivationFunctionを使用することができます。

データの暗号化にどの暗号化アルゴリズムを使用するかはわかりませんが、広く使用され、安全であることがわかっているものを選択することをお勧めします。特に、AESを使用することをお勧めします。また、SHAダイジェスト関数の1つを使用することをお勧めします(おそらくPasswordBasedKeyDerivationFunctionへの入力として)。SHA-2は最新ですが、キー生成の目的にはSHA-1で十分です。

また、生成しようとしているキーの長さも指定しませんが、キーのエントロピーの量は、使用するパスフレーズの長さに依存することに注意してください。パスフレーズが非常に長い場合を除き、次のようになります。理想的に必要な鍵長よりはるかに短い。

このスキームの最も弱いリンクはパスフレーズ自体であり、それは常に達成できるセキュリティのレベルを制限します。(実行しているように)データをソルトし、ブルートフォース攻撃を遅らせるためにキー生成に費用がかかる限り、問題はありません。

于 2010-12-01T19:01:43.187 に答える
1

私が必要としているのは、乱数とパスフレーズのシードであり、64ビットまたは128ビットの数値ブロックをインデックス付きで生成できる決定論的CSPRNGです。架空のCSPRNGのインデックス要素の1つとして「1970年1月1日」から数週間を使用すると、時間の経過とともにキーを自動的に変更するシステムを構築できるはずです。

さて、解決策の一部は、非時間ベースのジェネレータを使用することだと思います。そうすれば、両方の側が同じシードで始まる場合、両方が同じランダムストリームを生成します。その上に「1970年第1週からの週」ロジックを重ねることができます。

これを行うには、を使用しますOFB_mode<T>::Encryption。OFBモードは。AdditiveCipherTemplate<T>から派生したを使用するため、ジェネレータとして使用できますRandomNumberGenerator

実際、Crpyto ++はジェネレーターを使用して、test.cpp何かが失敗した場合に結果を再現できるようにします。使用方法は次のとおりですOFB_mode<T>::Encryption。それはまた適用されCTR_Mode<T>::Encryptionます:

SecByteBlock seed(32 + 16);
OS_GenerateRandomBlock(false, seed, seed.size());

for(unsigned int i = 0; i < 10; i++)
{
    OFB_Mode<AES>::Encryption prng;
    prng.SetKeyWithIV(seed, 32, seed + 32, 16);

    SecByteBlock t(16);
    prng.GenerateBlock(t, t.size());

    string s;
    HexEncoder hex(new StringSink(s));

    hex.Put(t, t.size());
    hex.MessageEnd();

    cout << "Random: " << s << endl;
}

の呼び出しは、OS_GenerateRandomBlockからバイトをフェッチし/dev/{u|s}random、それをシミュレートされた共有シードとして使用します。プログラムの実行ごとに異なります。プログラムを実行するたびに、次のように出力されます。

$ ./cryptopp-test.exe
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD

同じことを行う別のジェネレーターが利用可能ですが、それはCrypto++ライブラリの一部ではありません。と呼ばれAES_RNG、AES-256に基づいています。これはヘッダーのみの実装であり、Crypto++wikiのRandomNumberGeneratorにあります。

Crypto++wikiのトピック「クラスの再現性」も参照してください。RandomNumberGenerator

于 2015-02-16T20:47:07.983 に答える