
Предположим, я зашифровал с помощью ключа «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
}