Каким образом IV встроен в зашифрованный файл, если вы его не указываете?

Каким образом IV встроен в зашифрованный файл, если вы его не указываете?

Предположим, я зашифровал с помощью ключа «1234» файл, содержащий «abcd» с помощью:

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

И, конечно же, я получаю ту же соль, ключ и внутривенное вливание, что и раньше.

Первый вопрос: в каком смысле «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

и я получаю то же самое БЕЗ предоставления iv!

salt=237F07334625A768
key=F746D2B53EB82F7129BAEB2FCE2C310F
iv =BA28DBA00442BD4BACEBCAE7C01BA412

Теперь, хотя я вижу соль в зашифрованном файле и предоставляю ключ программе, я не ввожу iv и не вижу iv в зашифрованном файле.

Поэтому второй вопрос: как программа расшифровки узнает 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
}

Связанный контент