Множественное шифрование частей файла openssl AES256 (присоединиться позже)

Для частичной загрузки файла и шифрования я хотел бы прочитать фрагменты (пример: 10 МБ) из большого файла (пример: 100 МБ), зашифровать фрагмент с помощью AES256 и загрузить фрагмент на сервер. На сервере фрагменты объединяются в один большой файл (который затем должен представлять собой полный зашифрованный файл).

Я хотел бы избежать полного шифрования файла (например: 100 МБ!) Перед тем, как вынимать фрагменты и отправлять их на сервер (накладные расходы ЦП, потому что мне сначала нужно будет скопировать весь файл и выполнить AES256 по всему файлу ).

Я попробовал следующее (пример для файла размером 16 МБ = 2 фрагмента = 1 * 10 МБ + 1 * 6 МБ)

1-й фрагмент составляет ~ 10 МБ, при условии, что размер фрагмента кратен 16 (AES_BLOCK_SIZE)

EVP_CIPHER_CTX e_ctx;
EVP_CIPHER_CTX_init(&e_ctx);
EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
EVP_EncryptUpdate(&e_ctx, enc_data, &outlen, unenc_data, chunksize_to_load_from_file_unencrypted);

Во время 1-го фрагмента я не вызываю EVP_EncryptFinal_ex(), потому что шифрование еще не завершено (может быть, проблема в этом?).

2-й фрагмент ~ 6 МБ, там я шифрую остальные данные, смещенные от &outlen выше.

EVP_CIPHER_CTX e_ctx;
EVP_CIPHER_CTX_init(&e_ctx);
EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
EVP_EncryptUpdate(&e_ctx, enc_data, &outlen, unenc_data, chunksize_to_load_from_file_unencrypted);
EVP_EncryptFinal_ex(&e_ctx, enc_data+outlen, &final_length);

На сервере соединяются две файловые части. Затем я могу расшифровать файл "успешно", тот же размер незашифрованного файла. Но при смещении ~10 МБ некоторые байты отличаются (16 байт! = AES_BLOCK_SIZE)

Любая идея? Может это прокладка? Это не только в конце? EVP_EncryptFinal_ex действует иначе, когда не проходит через весь файл через EVP_EncryptUpdate?

Как я могу выполнить передачу зашифрованного фрагмента файла и объединить их на сервере, чтобы получить правильный зашифрованный файл?

Спасибо!


person Jonas Schnelli    schedule 04.09.2012    source источник
comment
Что такое 100 МБ в наши дни? Который может зашифровать за секунду!   -  person Maarten Bodewes    schedule 05.09.2012
comment
Например, 100 МБ, также может быть до ‹ = 2 ГБ. Я кодирую демон фоновой синхронизации, где шифрование AES256 может занять несколько важных тактов ЦП, которые пользователю не понравятся....   -  person Jonas Schnelli    schedule 05.09.2012


Ответы (2)


Вы используете неправильный вектор инициализации для второго фрагмента. При CBC iv последующего шифрования должно быть последним 16 байт предыдущего зашифрованного текста. Таким образом, просто объединение зашифрованных частей дает шифрование целого.

person Keith Randall    schedule 04.09.2012
comment
Проверим это. Создавал свой IV с помощью EVP_BytesToKey, может быть, IV получается случайным образом?! - person Jonas Schnelli; 05.09.2012
comment
Любой способ генерации начального iv будет работать (хотя для безопасности он должен генерироваться случайным образом). Однако iv предназначен только для первого блока. iv для последующих блоков — это просто зашифрованный текст из предыдущего блока. См. ссылку CBC для изображения. - person Keith Randall; 05.09.2012

Обычно для этого используется шифрование в режиме счетчика, но это кажется недоступным для OpenSSL. С блочными шифрами OpenSSL вы не можете просто начать шифрование/дешифрование в середине файла. Для CBC вам нужно знать предыдущий зашифрованный блок и вставить его как IV. Если вы зашифруете их последовательно на клиенте, вы сможете относительно легко расшифровать их на сервере.

Конечно, вы также можете зашифровать каждый блок отдельно, а затем объединить расшифрованные блоки вместе.

person Maarten Bodewes    schedule 04.09.2012