web-dev-qa-db-ja.com

openssl enc -aes-256-cbc -a -saltがファイルサイズを増やすのはなぜですか?

Amazon Glacierへの自動差分バックアップにopenssl enc -aes-256-cbc -a -saltを使用しています。しかし、このコマンドを使用すると、ファイルサイズがほぼ完全に35%増加することに気付きました。
私の理解では、ブロック暗号はファイルサイズをそれほど変更すべきではありません。私の知る限り、パディングを作成するために最後に最大16バイトが追加されることがわかっています。しかし、それは私のバックアップで17MB以上を占めていません。

このサイズの増加の原因は何ですか?

ログ行:

09:09:16 Created tarbal of 165 files of size            106M
09:09:50 Created /archief/2014-05-10.encrypted of size  143M

09:09:11 Created tarbal of 186 files of size            132M
09:09:52 Created /archief/2014-05-17.encrypted of size  179M
5
gnur

主な増加は-aフラグで、これは base64 が暗号文をエンコードすることを意味します。

man encから:

NAME
   enc - symmetric cipher routines

SYNOPSIS
   openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a] [-A] [-k password]
   [-kfile filename] [-K key] [-iv IV] [-p] [-P] [-bufsize number] [-nopad] [-debug]

   [...]

   -a  base64 process the data. This means that if encryption is taking place the data is base64 encoded
       after encryption. If decryption is set then the input data is base64 decoded before being
       decrypted.

Base64エンコーディングは、バイナリデータの3バイトごとに1バイトであることを意味します(1バイトは8ビットの数値であり、0〜2の値を持つことを意味します)8-1 = 255)4バイトの6ビットデータ(値0〜2)にエンコードされています6-1 = 63、ただし印刷可能ASCII記号)で表されます。 Base64は、64個の値のシンボルを印刷可能に選択できるので便利ですASCII文字(たとえば、通常0 = 'A'、1 = 'B'、... 25 = 'Z '、26 =' a '、... 51 =' z '、52 =' 0 '、...、61 =' 9 '、62 =' + '、63 ='/'ただし、最後の2つはしばしば3つのバイト8 * 3は24ビットであり、base64でエンコードされた数値の4つのグループ6 * 4も同様です。

たとえば、暗号文が3バイト(16進数)の場合:f0 bb 5c(240、187、92)バイナリでは、3バイトにグループ化されたビットは次のようになります。

 11110000 10111011 01011100

base64では、6ビットの4つのグループにグループ化されることを除いて、同じビットになります。

 111100 001011 101101 011100

これは、値60、11、45、28にマップします。これは、典型的なbase64テーブルでは、印刷可能なASCII characters 8Ltcにマップします。 3バイトのうち、base64エンコーディングなしでは取得されます)。

したがって、base64エンコーディングでは、およそ33%のファイルの増加を考慮する必要があります。 opensslは、base64エンコードされたasciiの64文字ごとに改行文字も追加するので、それより少し多くなります(したがって、テキストは64バイトで折り返されます)。これら2つの機能を合わせると、一般的なファイルサイズの増加は(4/3 * 65/64-1)= 35.4%になります。

あなたのスキームからのオーバーヘッドも少しあります。 -saltを指定すると、プレーンテキストのパスワードが取得され、ソルトが使用されたことを指定するヘッダーSalted__とともにランダムな8バイトのソルトがメッセージに連結され、これらもbase64でエンコードされます。 (ソルトの目的は、攻撃者が一般的なパスワードのレインボーテーブルを事前に計算するのに費用対効果が低くなるようにすることです)。スキームでランダムファイルを暗号化した場合(openssl enc -aes-256-cbc -a -salt -S DEADBEEFDEADBEEFを使用してソルトをDEADBEEFDEADBEEFとして指定すると、暗号化されたファイルの最初の行は

U2FsdGVkX1/erb7v3q2+7ybJfdPaLlVzOp7lKpOljvNK8ONCrgFrQpaJHQ8EqO1X

デコード(Pythonを使用):

>>> import base64
>>> base64.b64decode("U2FsdGVkX1/erb7v3q2+7ybJfdPaLlVzOp7lKpOljvNK8ONCrgFrQpaJHQ8EqO1X")
'Salted__\xde\xad\xbe\xef\xde\xad\xbe\xef&\xc9}\xd3\xda.Us:\x9e\xe5*\x93\xa5\x8e\xf3J\xf0\xe3B\xae\x01kB\x96\x89\x1d\x0f\x04\xa8\xedW'

Base64エンコーディング、改行、ソルトを組み合わせて、 初期化ベクトル(CBCモードの場合)、およびパディング(AESの128ビットブロックになるように均等に割り切れるようにするため)では、35%までのオーバーヘッドは完全に妥当と思われます。

編集:実際には、opensslはソルトを使用してパスワードからキーを導出するときに初期化ベクトルを格納しません。 man encから:「他のオプションのいずれかを使用してパスワードが指定されている場合、IVはこのパスワードから生成されます。」これを使用していくつかのテストファイルを実行すると、ファイルサイズは完全に一致します。 salt 8バイトとSalted__は、ファイルに16バイトを追加します。ファイルは16バイトの倍数になるように埋め込まれます(最大で16バイトが追加されます)。 base64エンコードを行わない場合、ファイルサイズは完全に一致し、base64 --wrap=64を適用すると、base64バージョンと完全に一致するファイルを取得できます。

11
dr jimbob