21

最近、自分のアプリケーションで暗号化を使い始めたので、入力テキストの長さと結果の暗号文との関係に困惑していることに気づきました。暗号化を適用する前は、データベースの列のサイズを簡単に判断できました。ただし、現在は列のサイズがわずかに異なります。

2 つの質問:

  1. これは、暗号の要件に適合するように、入力のパディングが原因であると想定するのは正しいですか?
  2. 入力の最大長に基づいて暗号文の最大長を正確に予測する方法はありますか?

ボーナスポイントとして、base64でエンコードされた暗号文をvarcharに保存するか、生のバイトとして保持してvarbinaryに保存する必要がありますか? データベースにバイトを格納することに伴うリスクはありますか (パラメーター化されたクエリを使用しているため、理論的には、エスケープを誤って壊すことは問題になりません)。

ティア!

補足: 私が使用している暗号は AES/Rijndael-256 です - この関係は利用可能なアルゴリズム間で異なりますか?

4

3 に答える 3

31

この関係は、使用しているパディングチェーンモード、およびアルゴリズムのブロックサイズ(ブロック暗号の場合)によって異なります。

一部の暗号化アルゴリズムは、データを「ビットごと」(または「バイトごと」)に暗号化するストリーム暗号です。それらのほとんどは、疑似ランダムバイトのキー依存ストリームを生成し、暗号化はそのストリームをデータとXORすることによって実行されます(復号化は同じです)。ストリーム暗号では、暗号化された長さはプレーンデータの長さと同じです。

他の暗号化アルゴリズムはブロック暗号です。ブロック暗号は、名目上、固定長のデータの単一ブロックを暗号化します。AESは、128ビットブロック(16バイト)のブロック暗号です。AES-256も128ビットブロックを使用することに注意してください。「256」は、ブロック長ではなく、キーの長さに関するものです。連鎖モードは、データをそのようないくつかのブロックに分割する方法に関するものです(これを安全に行うのは簡単ではありませんが、CBCモードは問題ありません)。チェーンモードによっては、データにパディングが必要になる場合があります。つまり、チェーンモードに適した長さになるように、最後に数バイトを追加する必要があります。パディングは、復号化するときに明確に削除できるようにする必要があります。

CBCモードでは、入力データの長さはブロック長の倍数である必要があるため、PKCS#5パディングを追加するのが通例です。ブロック長がnの場合、少なくとも1バイト、最大でnが追加され、合計サイズはnの倍数であり、最後に追加されたバイト(場合によってはすべて)の数値はkです。ここで、kは追加されたバイト数です。復号化時に、最後に復号化されたバイトを調べてkを回復し、最終的に削除する必要のあるパディングバイトの数を知るだけで十分です。

したがって、CBCモードとAESでは、PKCS#5のパディングを想定して、入力データの長さがdの場合、暗号化された長さは。になり(d + 16) & ~15ます。ここではCのような表記を使用しています。簡単に言うと、長さはd+1からd+16の間で、16の倍数です。

ブロック暗号がカウンターの連続する値を暗号化し、疑似ランダムバイトのストリームを生成するCTR(「カウンター」として)と呼ばれるモードがあります。これにより、ブロック暗号が事実上ストリーム暗号に変換され、長さdのメッセージがdバイトに暗号化されます。

警告:すべての暗号化システム(ストリーム暗号を含む)とモードについては、IV(初期値)と呼ばれる追加の値が必要です。各メッセージにはIVがあり、同じキーで暗号化された2つのメッセージが同じIVを使用することはできません。一部のモードには追加の要件があります。特に、CBCとCTRの両方について、IVは、暗号的に強力な疑似乱数ジェネレーターを使用してランダムかつ均一に選択する必要があります。IVは秘密ではありませんが、解読者が知っている必要があります。各メッセージは独自のIVを取得するため、暗号化されたメッセージと一緒にIVをエンコードする必要があることがよくあります。CBCまたはCTRの場合、IVの長さはnであるため、AESの場合は16バイト余分になります。mcryptがIVで何をするのかはわかりませんが、暗号的に言えば、IVはある時点で管理する必要があります。

Base64の場合、テキストのみのメディアを介してバイナリデータを転送するのに適していますが、適切なデータベースでは必要ありません。また、Base64はデータを約33%拡大するため、盲目的に適用しないでください。ここではBase64を避けるのが最善だと思います。

于 2010-09-15T12:26:57.230 に答える
1

私の理解では、ブロック モード (cbc、ecb) では、mcrypt_enc_get_block_size によって返されるように、出力の長さがブロック サイズに丸められます。さらに、データとともに IV を保存する必要があるため、サイズは strlen(data) + mcrypt_enc_get_iv_size() で丸められます。

base64 エンコーディングに関しては、気にしません (ただし、db をダンプするときは必ず 16 進エンコーディングを使用してください)。

于 2010-09-15T11:02:22.550 に答える
1

PKCS#5 パディングを使用した AES CBC ブロック暗号の場合、

#define BLOCKSIZE 16

size_t CipherTextLen = (PlainTxtLen / BLOCKSIZE + 1) * BLOCKSIZE;

これは初期化ベクトルを考慮していません

于 2010-09-15T13:19:13.350 に答える