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,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&amp; pa @@ -415,10 +412,7 @@ QPDF::EncryptionData::compute_encryption_key_from_password(std::string const&amp; 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();