diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index d2f4c87..a7b0a41 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -511,18 +511,12 @@ class QPDF std::string recover_encryption_key_with_password(std::string const& password, bool& perms_valid) const; - void compute_encryption_O_U( - char const* user_password, char const* owner_password, std::string& O, std::string& U); - - void compute_encryption_parameters_V5( - char const* user_password, - char const* owner_password, - std::string& encryption_key, - std::string& O, - std::string& U, - std::string& OE, - std::string& UE, - std::string& Perms); + void compute_encryption_O_U(char const* user_password, char const* owner_password); + + std::string + compute_encryption_parameters_V5(char const* user_password, char const* owner_password); + + std::string compute_parameters(char const* user_password, char const* owner_password); private: static constexpr unsigned int OU_key_bytes_V4 = 16; // ( == sizeof(MD5::Digest) diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 685a0bd..6bb2c17 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -619,34 +619,22 @@ QPDFWriter::setEncryptionParameters( P = ~P; generateID(); - std::string O; - std::string U; - std::string OE; - std::string UE; - std::string Perms; - std::string encryption_key; - if (V < 5) { - QPDF::compute_encryption_O_U( - user_password, owner_password, V, R, key_len, P, m->encrypt_metadata, m->id1, O, U); - } else { - QPDF::compute_encryption_parameters_V5( - user_password, - owner_password, - V, - R, - key_len, - P, - m->encrypt_metadata, - m->id1, - encryption_key, - O, - U, - OE, - UE, - Perms); - } + QPDF::EncryptionData encryption_data( + V, R, key_len, P, "", "", "", "", "", m->id1, m->encrypt_metadata); + auto encryption_key = encryption_data.compute_parameters(user_password, owner_password); setEncryptionParametersInternal( - V, R, key_len, P, O, U, OE, UE, Perms, m->id1, user_password, encryption_key); + V, + R, + key_len, + P, + encryption_data.getO(), + encryption_data.getU(), + encryption_data.getOE(), + encryption_data.getUE(), + encryption_data.getPerms(), + m->id1, + user_password, + encryption_key); } void diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index f2d8dfd..192aff6 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -1116,23 +1116,23 @@ QPDF::compute_encryption_O_U( int P, bool encrypt_metadata, std::string const& id1, - std::string& O, - std::string& U) + std::string& out_O, + std::string& out_U) { - EncryptionData(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata) - .compute_encryption_O_U(user_password, owner_password, O, U); + EncryptionData data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata); + data.compute_encryption_O_U(user_password, owner_password); + out_O = data.getO(); + out_U = data.getU(); } void -QPDF::EncryptionData::compute_encryption_O_U( - char const* user_password, char const* owner_password, std::string& out_O, std::string& out_U) +QPDF::EncryptionData::compute_encryption_O_U(char const* user_password, char const* owner_password) { if (V >= 5) { throw std::logic_error("compute_encryption_O_U called for file with V >= 5"); } - setO(compute_O_value(user_password, owner_password)); - out_O = getO(); - out_U = compute_U_value(user_password); + O = compute_O_value(user_password, owner_password); + U = compute_U_value(user_password); } void @@ -1146,44 +1146,53 @@ QPDF::compute_encryption_parameters_V5( bool encrypt_metadata, std::string const& id1, std::string& encryption_key, - std::string& O, - std::string& U, - std::string& OE, - std::string& UE, - std::string& Perms) -{ - EncryptionData(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata) - .compute_encryption_parameters_V5( - user_password, owner_password, encryption_key, O, U, OE, UE, Perms); -} - -void -QPDF::EncryptionData::compute_encryption_parameters_V5( - char const* user_password, - char const* owner_password, - std::string& out_encryption_key, std::string& out_O, std::string& out_U, std::string& out_OE, std::string& out_UE, std::string& out_Perms) { - out_encryption_key = util::random_string(key_bytes); + EncryptionData data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata); + encryption_key = data.compute_encryption_parameters_V5(user_password, owner_password); + + out_O = data.getO(); + out_U = data.getU(); + out_OE = data.getOE(); + out_UE = data.getUE(); + out_Perms = data.getPerms(); +} + +std::string +QPDF::EncryptionData::compute_encryption_parameters_V5( + char const* user_password, char const* owner_password) +{ + auto out_encryption_key = util::random_string(key_bytes); // Algorithm 8 from the PDF 2.0 auto validation_salt = util::random_string(8); auto key_salt = util::random_string(8); - out_U = hash_V5(user_password, validation_salt, "").append(validation_salt).append(key_salt); + U = hash_V5(user_password, validation_salt, "").append(validation_salt).append(key_salt); auto intermediate_key = hash_V5(user_password, key_salt, ""); - out_UE = process_with_aes(intermediate_key, true, out_encryption_key); + UE = process_with_aes(intermediate_key, true, out_encryption_key); // Algorithm 9 from the PDF 2.0 validation_salt = util::random_string(8); key_salt = util::random_string(8); - out_O = hash_V5(owner_password, validation_salt, out_U) + validation_salt + key_salt; - intermediate_key = hash_V5(owner_password, key_salt, out_U); - out_OE = process_with_aes(intermediate_key, true, out_encryption_key); + O = hash_V5(owner_password, validation_salt, U) + validation_salt + key_salt; + intermediate_key = hash_V5(owner_password, key_salt, U); + OE = process_with_aes(intermediate_key, true, out_encryption_key); // Algorithm 10 from the PDF 2.0 - out_Perms = process_with_aes(out_encryption_key, true, compute_Perms_value_V5_clear()); - setV5EncryptionParameters(out_O, out_OE, out_U, out_UE, out_Perms); + Perms = process_with_aes(out_encryption_key, true, compute_Perms_value_V5_clear()); + return out_encryption_key; +} + +std::string +QPDF::EncryptionData::compute_parameters(char const* user_password, char const* owner_password) +{ + if (V < 5) { + compute_encryption_O_U(user_password, owner_password); + return {}; + } else { + return compute_encryption_parameters_V5(user_password, owner_password); + } } std::string const&