Commit e81abdcce0d73e0dc2eef3b0f553502e86c1cc37

Authored by m-holger
1 parent 0d68cd73

Refactor `QPDF_encryption` and `MD5` to streamline digest handling, replace raw …

…arrays with `std::string`, and simplify key computation logic.
libqpdf/MD5.cc
... ... @@ -88,6 +88,24 @@ MD5::digest(Digest result)
88 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 109 void
92 110 MD5::print()
93 111 {
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -191,16 +191,18 @@ pad_or_truncate_password_V4(std::string password)
191 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 198 md5.digest(digest);
198   -
  199 + auto len = std::min(QIntC::to_size(key_len), sizeof(digest));
199 200 for (int i = 0; i < iterations; ++i) {
200 201 MD5 m;
201   - m.encodeDataIncrementally(reinterpret_cast<char*>(digest), QIntC::to_size(key_len));
  202 + m.encodeDataIncrementally(reinterpret_cast<char*>(digest), len);
202 203 m.digest(digest);
203 204 }
  205 + return {reinterpret_cast<char*>(digest), len};
204 206 }
205 207  
206 208 static void
... ... @@ -363,12 +365,7 @@ QPDF::compute_data_key(
363 365 if (use_aes) {
364 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 371 std::string
... ... @@ -415,10 +412,7 @@ QPDF::EncryptionData::compute_encryption_key_from_password(std::string const&amp; pa
415 412 if (getR() >= 4 && !getEncryptMetadata()) {
416 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 418 std::string
... ... @@ -428,16 +422,10 @@ QPDF::EncryptionData::compute_O_rc4_key(
428 422 if (getV() >= 5) {
429 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 426 MD5 md5;
436 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 431 std::string
... ...
libqpdf/qpdf/MD5.hh
... ... @@ -41,6 +41,8 @@ class MD5
41 41  
42 42 // computes a raw digest
43 43 void digest(Digest);
  44 + std::string digest();
  45 + static std::string digest(std::string_view data);
44 46  
45 47 // prints the digest to stdout terminated with \r\n (primarily for testing)
46 48 void print();
... ...