Commit e81abdcce0d73e0dc2eef3b0f553502e86c1cc37
1 parent
0d68cd73
Refactor `QPDF_encryption` and `MD5` to streamline digest handling, replace raw …
…arrays with `std::string`, and simplify key computation logic.
Showing
3 changed files
with
30 additions
and
22 deletions
libqpdf/MD5.cc
| @@ -88,6 +88,24 @@ MD5::digest(Digest result) | @@ -88,6 +88,24 @@ MD5::digest(Digest result) | ||
| 88 | crypto->MD5_digest(result); | 88 | crypto->MD5_digest(result); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | +std::string | ||
| 92 | +MD5::digest() | ||
| 93 | +{ | ||
| 94 | + Digest digest_val; | ||
| 95 | + digest(digest_val); | ||
| 96 | + return {reinterpret_cast<char*>(digest_val), 16}; | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +std::string | ||
| 100 | +MD5::digest(std::string_view data) | ||
| 101 | +{ | ||
| 102 | + MD5 m; | ||
| 103 | + m.encodeDataIncrementally(data.data(), data.size()); | ||
| 104 | + Digest digest_val; | ||
| 105 | + m.digest(digest_val); | ||
| 106 | + return {reinterpret_cast<char*>(digest_val), 16}; | ||
| 107 | +} | ||
| 108 | + | ||
| 91 | void | 109 | void |
| 92 | MD5::print() | 110 | MD5::print() |
| 93 | { | 111 | { |
libqpdf/QPDF_encryption.cc
| @@ -191,16 +191,18 @@ pad_or_truncate_password_V4(std::string password) | @@ -191,16 +191,18 @@ pad_or_truncate_password_V4(std::string password) | ||
| 191 | return password; | 191 | return password; |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | -static void | ||
| 195 | -iterate_md5_digest(MD5& md5, MD5::Digest& digest, int iterations, int key_len) | 194 | +static std::string |
| 195 | +iterate_md5_digest(MD5& md5, int iterations, int key_len) | ||
| 196 | { | 196 | { |
| 197 | + MD5::Digest digest; | ||
| 197 | md5.digest(digest); | 198 | md5.digest(digest); |
| 198 | - | 199 | + auto len = std::min(QIntC::to_size(key_len), sizeof(digest)); |
| 199 | for (int i = 0; i < iterations; ++i) { | 200 | for (int i = 0; i < iterations; ++i) { |
| 200 | MD5 m; | 201 | MD5 m; |
| 201 | - m.encodeDataIncrementally(reinterpret_cast<char*>(digest), QIntC::to_size(key_len)); | 202 | + m.encodeDataIncrementally(reinterpret_cast<char*>(digest), len); |
| 202 | m.digest(digest); | 203 | m.digest(digest); |
| 203 | } | 204 | } |
| 205 | + return {reinterpret_cast<char*>(digest), len}; | ||
| 204 | } | 206 | } |
| 205 | 207 | ||
| 206 | static void | 208 | static void |
| @@ -363,12 +365,7 @@ QPDF::compute_data_key( | @@ -363,12 +365,7 @@ QPDF::compute_data_key( | ||
| 363 | if (use_aes) { | 365 | if (use_aes) { |
| 364 | result += "sAlT"; | 366 | result += "sAlT"; |
| 365 | } | 367 | } |
| 366 | - | ||
| 367 | - MD5 md5; | ||
| 368 | - md5.encodeDataIncrementally(result); | ||
| 369 | - MD5::Digest digest; | ||
| 370 | - md5.digest(digest); | ||
| 371 | - return {reinterpret_cast<char*>(digest), std::min(result.length(), toS(16))}; | 368 | + return MD5::digest(result).substr(0, result.size()); |
| 372 | } | 369 | } |
| 373 | 370 | ||
| 374 | std::string | 371 | std::string |
| @@ -415,10 +412,7 @@ QPDF::EncryptionData::compute_encryption_key_from_password(std::string const& pa | @@ -415,10 +412,7 @@ QPDF::EncryptionData::compute_encryption_key_from_password(std::string const& pa | ||
| 415 | if (getR() >= 4 && !getEncryptMetadata()) { | 412 | if (getR() >= 4 && !getEncryptMetadata()) { |
| 416 | md5.encodeDataIncrementally("\xff\xff\xff\xff"); | 413 | md5.encodeDataIncrementally("\xff\xff\xff\xff"); |
| 417 | } | 414 | } |
| 418 | - MD5::Digest digest; | ||
| 419 | - int key_len = std::min(toI(sizeof(digest)), getLengthBytes()); | ||
| 420 | - iterate_md5_digest(md5, digest, (getR() >= 3 ? 50 : 0), key_len); | ||
| 421 | - return {reinterpret_cast<char*>(digest), toS(key_len)}; | 415 | + return iterate_md5_digest(md5, (getR() >= 3 ? 50 : 0), getLengthBytes()); |
| 422 | } | 416 | } |
| 423 | 417 | ||
| 424 | std::string | 418 | std::string |
| @@ -428,16 +422,10 @@ QPDF::EncryptionData::compute_O_rc4_key( | @@ -428,16 +422,10 @@ QPDF::EncryptionData::compute_O_rc4_key( | ||
| 428 | if (getV() >= 5) { | 422 | if (getV() >= 5) { |
| 429 | throw std::logic_error("compute_O_rc4_key called for file with V >= 5"); | 423 | throw std::logic_error("compute_O_rc4_key called for file with V >= 5"); |
| 430 | } | 424 | } |
| 431 | - std::string password = owner_password; | ||
| 432 | - if (password.empty()) { | ||
| 433 | - password = user_password; | ||
| 434 | - } | 425 | + std::string password = owner_password.empty() ? user_password : owner_password; |
| 435 | MD5 md5; | 426 | MD5 md5; |
| 436 | md5.encodeDataIncrementally(pad_or_truncate_password_V4(password)); | 427 | md5.encodeDataIncrementally(pad_or_truncate_password_V4(password)); |
| 437 | - MD5::Digest digest; | ||
| 438 | - int key_len = std::min(QIntC::to_int(sizeof(digest)), getLengthBytes()); | ||
| 439 | - iterate_md5_digest(md5, digest, (getR() >= 3 ? 50 : 0), key_len); | ||
| 440 | - return {reinterpret_cast<const char*>(digest), OU_key_bytes_V4}; | 428 | + return iterate_md5_digest(md5, (getR() >= 3 ? 50 : 0), getLengthBytes()); |
| 441 | } | 429 | } |
| 442 | 430 | ||
| 443 | std::string | 431 | std::string |
libqpdf/qpdf/MD5.hh
| @@ -41,6 +41,8 @@ class MD5 | @@ -41,6 +41,8 @@ class MD5 | ||
| 41 | 41 | ||
| 42 | // computes a raw digest | 42 | // computes a raw digest |
| 43 | void digest(Digest); | 43 | void digest(Digest); |
| 44 | + std::string digest(); | ||
| 45 | + static std::string digest(std::string_view data); | ||
| 44 | 46 | ||
| 45 | // prints the digest to stdout terminated with \r\n (primarily for testing) | 47 | // prints the digest to stdout terminated with \r\n (primarily for testing) |
| 46 | void print(); | 48 | void print(); |