IV を指定しない場合、IV は暗号化されたファイルにどのように埋め込まれるのでしょうか?

IV を指定しない場合、IV は暗号化されたファイルにどのように埋め込まれるのでしょうか?

「abcd」を含むファイルをキー「1234」で暗号化するとします。

openssl enc -iv BABA -aes128 -in file.txt -out file.enc -p

次のような結果になります:

salt=1B929D9049534D22
key=0326A1E8F4875B26FE2D04E02425C5AD
iv =BABA0000000000000000000000000000

ここまでは順調ですね。

以下の方法でファイルを復号化できます:

openssl enc -d -aes128 -iv BABA -in file1.enc -out file1.dec.txt -p

そして明らかに、以前と同じソルト、キー、iv を取得します。

最初の質問は、「0326A1E8F4875B26FE2D04E02425C5AD」がどのような意味で「キー」なのかということです。

私のキー「1234」との関係は?(MD5ハッシュのようです。でも...何の関係があるのでしょうか?)

続けましょう。今度は、iv を指定せずに同じこと (同じプレーンテキスト、同じキー) を実行します。

openssl enc -aes128 -in file.txt -out file2.enc -p

次のような結果になります:

salt=237F07334625A768
key=F746D2B53EB82F7129BAEB2FCE2C310F
iv =BA28DBA00442BD4BACEBCAE7C01BA412

ここで次のように復号します:

openssl enc -d -aes128 -in file2.enc -out file2.dec.txt -p

そして、点滴をしなくても同じ結果が得られます!

salt=237F07334625A768
key=F746D2B53EB82F7129BAEB2FCE2C310F
iv =BA28DBA00442BD4BACEBCAE7C01BA412

現在、暗号化されたファイル内の salt は表示でき、プログラムにキーを提供していますが、iv は入力しておらず、暗号化されたファイル内の iv も表示できません。

したがって、2 番目の質問は、復号化プログラムは、ファイルの復号化に必要な iv をどのようにして知るのかということです。言い換えると、iv が暗号化されたファイルに埋め込まれている場合 (ソルトのように)、どのように行われるのでしょうか。

答え1

キーと IV は両方とも PBKDF を使用してパスワードから計算されます。OpenSSL の場合、使用される方法は ですEVP_BytesToKey。これは、多くの反復を使用しない PBKDF1 に似た関数です。ソルトは PBKDF への入力パラメータです。これにより、同じパスワードを使用しても、キーと IV が常に異なることが保証されます。

ソースコードを見ることができますここキーと IV の導出がどのように行われるかを知る (EVP_BytesToKeyあまりよく説明されていないが、これは OpenSSL 内の独自のメカニズムである)。

基本的に、暗号化中は次のようになります。

openssl_encrypt(password: string, plaintext: bytes): bytes
{
    salt:bytes = random(8) # 8 bytes = 64 bits
    iterations:int = 1
    key:bytes, iv:bytes = pbkdf(password, iterations, salt)
    ciphertext:bytes = encrypt_aes_cbc_pkcs7padding(key, iv, plaintext)
    encoded_ciphertext:bytes = "Salted__" | salt | ciphertext
    return encoded_ciphertext
}

これが復号化です:

openssl_decrypt(password:string, encoded_ciphertext:bytes)
{
    salt:bytes = take(encoded_ciphertext, from: 8, size: 8) # 8 bytes = 64 bits
    ciphertext:bytes = take(encoded_ciphertext, from: 16, size: sizeof(encoded_ciphertext - 16)
    iterations:int = 1
    key:bytes, iv:bytes = pbkdf(password, iterations, salt)
    plaintext:bytes = decrypt_aes_cbc_pkcs7padding(key, iv, ciphertext)
    return plaintext
}

関連情報