Commit d6ce922e4f03fd32940ce22f59997ffdc4f39100

Authored by m-holger
1 parent 070b38bf

Refactor `QPDF::EncryptionData`: move to private `QPDF::Doc::Encryption` and update references.

include/qpdf/QPDF.hh
@@ -472,7 +472,7 @@ class QPDF @@ -472,7 +472,7 @@ class QPDF
472 V(V), 472 V(V),
473 R(R), 473 R(R),
474 Length_bytes(Length_bytes), 474 Length_bytes(Length_bytes),
475 - P(static_cast<unsigned long long>(P)), 475 + P(P),
476 O(O), 476 O(O),
477 U(U), 477 U(U),
478 OE(OE), 478 OE(OE),
@@ -482,20 +482,11 @@ class QPDF @@ -482,20 +482,11 @@ class QPDF
482 encrypt_metadata(encrypt_metadata) 482 encrypt_metadata(encrypt_metadata)
483 { 483 {
484 } 484 }
485 - EncryptionData(int V, int R, int Length_bytes, bool encrypt_metadata) :  
486 - V(V),  
487 - R(R),  
488 - Length_bytes(Length_bytes),  
489 - encrypt_metadata(encrypt_metadata)  
490 - {  
491 - }  
492 485
493 int getV() const; 486 int getV() const;
494 int getR() const; 487 int getR() const;
495 int getLengthBytes() const; 488 int getLengthBytes() const;
496 int getP() const; 489 int getP() const;
497 - // Bits in P are numbered from 1 as in the PDF spec.  
498 - bool getP(size_t bit) const;  
499 std::string const& getO() const; 490 std::string const& getO() const;
500 std::string const& getU() const; 491 std::string const& getU() const;
501 std::string const& getOE() const; 492 std::string const& getOE() const;
@@ -503,12 +494,9 @@ class QPDF @@ -503,12 +494,9 @@ class QPDF
503 std::string const& getPerms() const; 494 std::string const& getPerms() const;
504 std::string const& getId1() const; 495 std::string const& getId1() const;
505 bool getEncryptMetadata() const; 496 bool getEncryptMetadata() const;
506 - // Bits in P are numbered from 1 as in the PDF spec.  
507 - void setP(size_t bit, bool val);  
508 - void setP(unsigned long val); 497 +
509 void setO(std::string const&); 498 void setO(std::string const&);
510 void setU(std::string const&); 499 void setU(std::string const&);
511 - void setId1(std::string const& val);  
512 void setV5EncryptionParameters( 500 void setV5EncryptionParameters(
513 std::string const& O, 501 std::string const& O,
514 std::string const& OE, 502 std::string const& OE,
@@ -516,51 +504,14 @@ class QPDF @@ -516,51 +504,14 @@ class QPDF
516 std::string const& UE, 504 std::string const& UE,
517 std::string const& Perms); 505 std::string const& Perms);
518 506
519 - std::string compute_encryption_key(std::string const& password) const;  
520 -  
521 - bool  
522 - check_owner_password(std::string& user_password, std::string const& owner_password) const;  
523 -  
524 - bool check_user_password(std::string const& user_password) const;  
525 -  
526 - std::string  
527 - recover_encryption_key_with_password(std::string const& password, bool& perms_valid) const;  
528 -  
529 - void compute_encryption_O_U(char const* user_password, char const* owner_password);  
530 -  
531 - std::string  
532 - compute_encryption_parameters_V5(char const* user_password, char const* owner_password);  
533 -  
534 - std::string compute_parameters(char const* user_password, char const* owner_password);  
535 -  
536 private: 507 private:
537 - static constexpr unsigned int OU_key_bytes_V4 = 16; // ( == sizeof(MD5::Digest)  
538 -  
539 EncryptionData(EncryptionData const&) = delete; 508 EncryptionData(EncryptionData const&) = delete;
540 EncryptionData& operator=(EncryptionData const&) = delete; 509 EncryptionData& operator=(EncryptionData const&) = delete;
541 510
542 - std::string hash_V5(  
543 - std::string const& password, std::string const& salt, std::string const& udata) const;  
544 - std::string  
545 - compute_O_value(std::string const& user_password, std::string const& owner_password) const;  
546 - std::string compute_U_value(std::string const& user_password) const;  
547 - std::string compute_encryption_key_from_password(std::string const& password) const;  
548 - std::string recover_encryption_key_with_password(std::string const& password) const;  
549 - bool check_owner_password_V4(  
550 - std::string& user_password, std::string const& owner_password) const;  
551 - bool check_owner_password_V5(std::string const& owner_passworda) const;  
552 - std::string compute_Perms_value_V5_clear() const;  
553 - std::string compute_O_rc4_key(  
554 - std::string const& user_password, std::string const& owner_password) const;  
555 - std::string compute_U_value_R2(std::string const& user_password) const;  
556 - std::string compute_U_value_R3(std::string const& user_password) const;  
557 - bool check_user_password_V4(std::string const& user_password) const;  
558 - bool check_user_password_V5(std::string const& user_password) const;  
559 -  
560 int V; 511 int V;
561 int R; 512 int R;
562 int Length_bytes; 513 int Length_bytes;
563 - std::bitset<32> P{0xfffffffc}; // Specification always requires bits 1 and 2 to be cleared. 514 + int P;
564 std::string O; 515 std::string O;
565 std::string U; 516 std::string U;
566 std::string OE; 517 std::string OE;
@@ -569,7 +520,6 @@ class QPDF @@ -569,7 +520,6 @@ class QPDF
569 std::string id1; 520 std::string id1;
570 bool encrypt_metadata; 521 bool encrypt_metadata;
571 }; 522 };
572 -  
573 QPDF_DLL 523 QPDF_DLL
574 bool isEncrypted() const; 524 bool isEncrypted() const;
575 525
libqpdf/QPDFWriter.cc
@@ -27,6 +27,8 @@ @@ -27,6 +27,8 @@
27 using namespace std::literals; 27 using namespace std::literals;
28 using namespace qpdf; 28 using namespace qpdf;
29 29
  30 +using Encryption = QPDF::Doc::Encryption;
  31 +
30 QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default) 32 QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default)
31 { 33 {
32 // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer 34 // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer
@@ -504,7 +506,7 @@ class QPDFWriter::Members: QPDF::Doc::Writer @@ -504,7 +506,7 @@ class QPDFWriter::Members: QPDF::Doc::Writer
504 bool pclm{false}; 506 bool pclm{false};
505 qpdf_object_stream_e object_stream_mode{qpdf_o_preserve}; 507 qpdf_object_stream_e object_stream_mode{qpdf_o_preserve};
506 508
507 - std::unique_ptr<QPDF::EncryptionData> encryption; 509 + std::unique_ptr<QPDF::Doc::Encryption> encryption;
508 std::string encryption_key; 510 std::string encryption_key;
509 bool encrypt_use_aes{false}; 511 bool encrypt_use_aes{false};
510 512
@@ -829,7 +831,7 @@ QPDFWriter::setR2EncryptionParametersInsecure( @@ -829,7 +831,7 @@ QPDFWriter::setR2EncryptionParametersInsecure(
829 bool allow_extract, 831 bool allow_extract,
830 bool allow_annotate) 832 bool allow_annotate)
831 { 833 {
832 - m->encryption = std::make_unique<QPDF::EncryptionData>(1, 2, 5, true); 834 + m->encryption = std::make_unique<Encryption>(1, 2, 5, true);
833 if (!allow_print) { 835 if (!allow_print) {
834 m->encryption->setP(3, false); 836 m->encryption->setP(3, false);
835 } 837 }
@@ -857,7 +859,7 @@ QPDFWriter::setR3EncryptionParametersInsecure( @@ -857,7 +859,7 @@ QPDFWriter::setR3EncryptionParametersInsecure(
857 bool allow_modify_other, 859 bool allow_modify_other,
858 qpdf_r3_print_e print) 860 qpdf_r3_print_e print)
859 { 861 {
860 - m->encryption = std::make_unique<QPDF::EncryptionData>(2, 3, 16, true); 862 + m->encryption = std::make_unique<Encryption>(2, 3, 16, true);
861 m->interpretR3EncryptionParameters( 863 m->interpretR3EncryptionParameters(
862 allow_accessibility, 864 allow_accessibility,
863 allow_extract, 865 allow_extract,
@@ -884,7 +886,7 @@ QPDFWriter::setR4EncryptionParametersInsecure( @@ -884,7 +886,7 @@ QPDFWriter::setR4EncryptionParametersInsecure(
884 bool encrypt_metadata, 886 bool encrypt_metadata,
885 bool use_aes) 887 bool use_aes)
886 { 888 {
887 - m->encryption = std::make_unique<QPDF::EncryptionData>(4, 4, 16, encrypt_metadata); 889 + m->encryption = std::make_unique<Encryption>(4, 4, 16, encrypt_metadata);
888 m->encrypt_use_aes = use_aes; 890 m->encrypt_use_aes = use_aes;
889 m->interpretR3EncryptionParameters( 891 m->interpretR3EncryptionParameters(
890 allow_accessibility, 892 allow_accessibility,
@@ -911,7 +913,7 @@ QPDFWriter::setR5EncryptionParameters( @@ -911,7 +913,7 @@ QPDFWriter::setR5EncryptionParameters(
911 qpdf_r3_print_e print, 913 qpdf_r3_print_e print,
912 bool encrypt_metadata) 914 bool encrypt_metadata)
913 { 915 {
914 - m->encryption = std::make_unique<QPDF::EncryptionData>(5, 5, 32, encrypt_metadata); 916 + m->encryption = std::make_unique<Encryption>(5, 5, 32, encrypt_metadata);
915 m->encrypt_use_aes = true; 917 m->encrypt_use_aes = true;
916 m->interpretR3EncryptionParameters( 918 m->interpretR3EncryptionParameters(
917 allow_accessibility, 919 allow_accessibility,
@@ -938,7 +940,7 @@ QPDFWriter::setR6EncryptionParameters( @@ -938,7 +940,7 @@ QPDFWriter::setR6EncryptionParameters(
938 qpdf_r3_print_e print, 940 qpdf_r3_print_e print,
939 bool encrypt_metadata) 941 bool encrypt_metadata)
940 { 942 {
941 - m->encryption = std::make_unique<QPDF::EncryptionData>(5, 6, 32, encrypt_metadata); 943 + m->encryption = std::make_unique<Encryption>(5, 6, 32, encrypt_metadata);
942 m->interpretR3EncryptionParameters( 944 m->interpretR3EncryptionParameters(
943 allow_accessibility, 945 allow_accessibility,
944 allow_extract, 946 allow_extract,
@@ -1094,7 +1096,7 @@ QPDFWriter::Members::copyEncryptionParameters(QPDF&amp; qpdf) @@ -1094,7 +1096,7 @@ QPDFWriter::Members::copyEncryptionParameters(QPDF&amp; qpdf)
1094 QTC::TC("qpdf", "QPDFWriter copy encrypt metadata", encrypt_metadata ? 0 : 1); 1096 QTC::TC("qpdf", "QPDFWriter copy encrypt metadata", encrypt_metadata ? 0 : 1);
1095 QTC::TC("qpdf", "QPDFWriter copy use_aes", encrypt_use_aes ? 0 : 1); 1097 QTC::TC("qpdf", "QPDFWriter copy use_aes", encrypt_use_aes ? 0 : 1);
1096 1098
1097 - encryption = std::make_unique<QPDF::EncryptionData>( 1099 + encryption = std::make_unique<Encryption>(
1098 V, 1100 V,
1099 encrypt.getKey("/R").getIntValueAsInt(), 1101 encrypt.getKey("/R").getIntValueAsInt(),
1100 key_len, 1102 key_len,
libqpdf/QPDF_encryption.cc
@@ -21,6 +21,8 @@ @@ -21,6 +21,8 @@
21 using namespace qpdf; 21 using namespace qpdf;
22 using namespace std::literals; 22 using namespace std::literals;
23 23
  24 +using Encryption = QPDF::Doc::Encryption;
  25 +
24 static std::string padding_string = 26 static std::string padding_string =
25 "\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56\xff\xfa\x01\x08" 27 "\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56\xff\xfa\x01\x08"
26 "\x2e\x2e\x00\xb6\xd0\x68\x3e\x80\x2f\x0c\xa9\xfe\x64\x53\x69\x7a"s; 28 "\x2e\x2e\x00\xb6\xd0\x68\x3e\x80\x2f\x0c\xa9\xfe\x64\x53\x69\x7a"s;
@@ -52,11 +54,104 @@ QPDF::EncryptionData::getLengthBytes() const @@ -52,11 +54,104 @@ QPDF::EncryptionData::getLengthBytes() const
52 int 54 int
53 QPDF::EncryptionData::getP() const 55 QPDF::EncryptionData::getP() const
54 { 56 {
  57 + return this->P;
  58 +}
  59 +
  60 +std::string const&
  61 +QPDF::EncryptionData::getO() const
  62 +{
  63 + return this->O;
  64 +}
  65 +
  66 +std::string const&
  67 +QPDF::EncryptionData::getU() const
  68 +{
  69 + return this->U;
  70 +}
  71 +
  72 +std::string const&
  73 +QPDF::EncryptionData::getOE() const
  74 +{
  75 + return this->OE;
  76 +}
  77 +
  78 +std::string const&
  79 +QPDF::EncryptionData::getUE() const
  80 +{
  81 + return this->UE;
  82 +}
  83 +
  84 +std::string const&
  85 +QPDF::EncryptionData::getPerms() const
  86 +{
  87 + return this->Perms;
  88 +}
  89 +
  90 +std::string const&
  91 +QPDF::EncryptionData::getId1() const
  92 +{
  93 + return this->id1;
  94 +}
  95 +
  96 +bool
  97 +QPDF::EncryptionData::getEncryptMetadata() const
  98 +{
  99 + return this->encrypt_metadata;
  100 +}
  101 +
  102 +void
  103 +QPDF::EncryptionData::setO(std::string const& O)
  104 +{
  105 + this->O = O;
  106 +}
  107 +
  108 +void
  109 +QPDF::EncryptionData::setU(std::string const& U)
  110 +{
  111 + this->U = U;
  112 +}
  113 +
  114 +void
  115 +QPDF::EncryptionData::setV5EncryptionParameters(
  116 + std::string const& O,
  117 + std::string const& OE,
  118 + std::string const& U,
  119 + std::string const& UE,
  120 + std::string const& Perms)
  121 +{
  122 + this->O = O;
  123 + this->OE = OE;
  124 + this->U = U;
  125 + this->UE = UE;
  126 + this->Perms = Perms;
  127 +}
  128 +
  129 +int
  130 +Encryption::getV() const
  131 +{
  132 + return this->V;
  133 +}
  134 +
  135 +int
  136 +Encryption::getR() const
  137 +{
  138 + return this->R;
  139 +}
  140 +
  141 +int
  142 +Encryption::getLengthBytes() const
  143 +{
  144 + return this->Length_bytes;
  145 +}
  146 +
  147 +int
  148 +Encryption::getP() const
  149 +{
55 return static_cast<int>(P.to_ulong()); 150 return static_cast<int>(P.to_ulong());
56 } 151 }
57 152
58 bool 153 bool
59 -QPDF::EncryptionData::getP(size_t bit) const 154 +Encryption::getP(size_t bit) const
60 { 155 {
61 qpdf_assert_debug(bit); 156 qpdf_assert_debug(bit);
62 return P.test(bit - 1); 157 return P.test(bit - 1);
@@ -70,80 +165,80 @@ QPDF::EncryptionParameters::P(size_t bit) const @@ -70,80 +165,80 @@ QPDF::EncryptionParameters::P(size_t bit) const
70 } 165 }
71 166
72 std::string const& 167 std::string const&
73 -QPDF::EncryptionData::getO() const 168 +Encryption::getO() const
74 { 169 {
75 return this->O; 170 return this->O;
76 } 171 }
77 172
78 std::string const& 173 std::string const&
79 -QPDF::EncryptionData::getU() const 174 +Encryption::getU() const
80 { 175 {
81 return this->U; 176 return this->U;
82 } 177 }
83 178
84 std::string const& 179 std::string const&
85 -QPDF::EncryptionData::getOE() const 180 +Encryption::getOE() const
86 { 181 {
87 return this->OE; 182 return this->OE;
88 } 183 }
89 184
90 std::string const& 185 std::string const&
91 -QPDF::EncryptionData::getUE() const 186 +Encryption::getUE() const
92 { 187 {
93 return this->UE; 188 return this->UE;
94 } 189 }
95 190
96 std::string const& 191 std::string const&
97 -QPDF::EncryptionData::getPerms() const 192 +Encryption::getPerms() const
98 { 193 {
99 return this->Perms; 194 return this->Perms;
100 } 195 }
101 196
102 std::string const& 197 std::string const&
103 -QPDF::EncryptionData::getId1() const 198 +Encryption::getId1() const
104 { 199 {
105 return this->id1; 200 return this->id1;
106 } 201 }
107 202
108 bool 203 bool
109 -QPDF::EncryptionData::getEncryptMetadata() const 204 +Encryption::getEncryptMetadata() const
110 { 205 {
111 return this->encrypt_metadata; 206 return this->encrypt_metadata;
112 } 207 }
113 208
114 void 209 void
115 -QPDF::EncryptionData::setO(std::string const& O) 210 +Encryption::setO(std::string const& O)
116 { 211 {
117 this->O = O; 212 this->O = O;
118 } 213 }
119 214
120 void 215 void
121 -QPDF::EncryptionData::setU(std::string const& U) 216 +Encryption::setU(std::string const& U)
122 { 217 {
123 this->U = U; 218 this->U = U;
124 } 219 }
125 220
126 void 221 void
127 -QPDF::EncryptionData::setP(size_t bit, bool val) 222 +Encryption::setP(size_t bit, bool val)
128 { 223 {
129 qpdf_assert_debug(bit); 224 qpdf_assert_debug(bit);
130 P.set(bit - 1, val); 225 P.set(bit - 1, val);
131 } 226 }
132 227
133 void 228 void
134 -QPDF::EncryptionData::setP(unsigned long val) 229 +Encryption::setP(unsigned long val)
135 { 230 {
136 P = std::bitset<32>(val); 231 P = std::bitset<32>(val);
137 } 232 }
138 233
139 void 234 void
140 -QPDF::EncryptionData::setId1(std::string const& val) 235 +Encryption::setId1(std::string const& val)
141 { 236 {
142 id1 = val; 237 id1 = val;
143 } 238 }
144 239
145 void 240 void
146 -QPDF::EncryptionData::setV5EncryptionParameters( 241 +Encryption::setV5EncryptionParameters(
147 std::string const& O, 242 std::string const& O,
148 std::string const& OE, 243 std::string const& OE,
149 std::string const& U, 244 std::string const& U,
@@ -246,7 +341,7 @@ process_with_aes( @@ -246,7 +341,7 @@ process_with_aes(
246 } 341 }
247 342
248 std::string 343 std::string
249 -QPDF::EncryptionData::hash_V5( 344 +Encryption::hash_V5(
250 std::string const& password, std::string const& salt, std::string const& udata) const 345 std::string const& password, std::string const& salt, std::string const& udata) const
251 { 346 {
252 Pl_SHA2 hash(256); 347 Pl_SHA2 hash(256);
@@ -358,13 +453,25 @@ QPDF::compute_data_key( @@ -358,13 +453,25 @@ QPDF::compute_data_key(
358 } 453 }
359 454
360 std::string 455 std::string
361 -QPDF::compute_encryption_key(std::string const& password, EncryptionData const& data)  
362 -{  
363 - return data.compute_encryption_key(password); 456 +QPDF::compute_encryption_key(std::string const& password, EncryptionData const& ed)
  457 +{
  458 + return Encryption(
  459 + ed.getV(),
  460 + ed.getR(),
  461 + ed.getLengthBytes(),
  462 + ed.getP(),
  463 + ed.getO(),
  464 + ed.getU(),
  465 + ed.getOE(),
  466 + ed.getUE(),
  467 + ed.getPerms(),
  468 + ed.getId1(),
  469 + ed.getEncryptMetadata())
  470 + .compute_encryption_key(password);
364 } 471 }
365 472
366 std::string 473 std::string
367 -QPDF::EncryptionData::compute_encryption_key(std::string const& password) const 474 +Encryption::compute_encryption_key(std::string const& password) const
368 { 475 {
369 if (getV() >= 5) { 476 if (getV() >= 5) {
370 // For V >= 5, the encryption key is generated and stored in the file, encrypted separately 477 // For V >= 5, the encryption key is generated and stored in the file, encrypted separately
@@ -378,7 +485,7 @@ QPDF::EncryptionData::compute_encryption_key(std::string const&amp; password) const @@ -378,7 +485,7 @@ QPDF::EncryptionData::compute_encryption_key(std::string const&amp; password) const
378 } 485 }
379 486
380 std::string 487 std::string
381 -QPDF::EncryptionData::compute_encryption_key_from_password(std::string const& password) const 488 +Encryption::compute_encryption_key_from_password(std::string const& password) const
382 { 489 {
383 // Algorithm 3.2 from the PDF 1.7 Reference Manual 490 // Algorithm 3.2 from the PDF 1.7 Reference Manual
384 491
@@ -405,7 +512,7 @@ QPDF::EncryptionData::compute_encryption_key_from_password(std::string const&amp; pa @@ -405,7 +512,7 @@ QPDF::EncryptionData::compute_encryption_key_from_password(std::string const&amp; pa
405 } 512 }
406 513
407 std::string 514 std::string
408 -QPDF::EncryptionData::compute_O_rc4_key( 515 +Encryption::compute_O_rc4_key(
409 std::string const& user_password, std::string const& owner_password) const 516 std::string const& user_password, std::string const& owner_password) const
410 { 517 {
411 if (getV() >= 5) { 518 if (getV() >= 5) {
@@ -418,7 +525,7 @@ QPDF::EncryptionData::compute_O_rc4_key( @@ -418,7 +525,7 @@ QPDF::EncryptionData::compute_O_rc4_key(
418 } 525 }
419 526
420 std::string 527 std::string
421 -QPDF::EncryptionData::compute_O_value( 528 +Encryption::compute_O_value(
422 std::string const& user_password, std::string const& owner_password) const 529 std::string const& user_password, std::string const& owner_password) const
423 { 530 {
424 // Algorithm 3.3 from the PDF 1.7 Reference Manual 531 // Algorithm 3.3 from the PDF 1.7 Reference Manual
@@ -431,7 +538,7 @@ QPDF::EncryptionData::compute_O_value( @@ -431,7 +538,7 @@ QPDF::EncryptionData::compute_O_value(
431 } 538 }
432 539
433 std::string 540 std::string
434 -QPDF::EncryptionData::compute_U_value_R2(std::string const& user_password) const 541 +Encryption::compute_U_value_R2(std::string const& user_password) const
435 { 542 {
436 // Algorithm 3.4 from the PDF 1.7 Reference Manual 543 // Algorithm 3.4 from the PDF 1.7 Reference Manual
437 544
@@ -443,7 +550,7 @@ QPDF::EncryptionData::compute_U_value_R2(std::string const&amp; user_password) const @@ -443,7 +550,7 @@ QPDF::EncryptionData::compute_U_value_R2(std::string const&amp; user_password) const
443 } 550 }
444 551
445 std::string 552 std::string
446 -QPDF::EncryptionData::compute_U_value_R3(std::string const& user_password) const 553 +Encryption::compute_U_value_R3(std::string const& user_password) const
447 { 554 {
448 // Algorithm 3.5 from the PDF 1.7 Reference Manual 555 // Algorithm 3.5 from the PDF 1.7 Reference Manual
449 556
@@ -460,7 +567,7 @@ QPDF::EncryptionData::compute_U_value_R3(std::string const&amp; user_password) const @@ -460,7 +567,7 @@ QPDF::EncryptionData::compute_U_value_R3(std::string const&amp; user_password) const
460 } 567 }
461 568
462 std::string 569 std::string
463 -QPDF::EncryptionData::compute_U_value(std::string const& user_password) const 570 +Encryption::compute_U_value(std::string const& user_password) const
464 { 571 {
465 if (getR() >= 3) { 572 if (getR() >= 3) {
466 return compute_U_value_R3(user_password); 573 return compute_U_value_R3(user_password);
@@ -470,7 +577,7 @@ QPDF::EncryptionData::compute_U_value(std::string const&amp; user_password) const @@ -470,7 +577,7 @@ QPDF::EncryptionData::compute_U_value(std::string const&amp; user_password) const
470 } 577 }
471 578
472 bool 579 bool
473 -QPDF::EncryptionData::check_user_password_V4(std::string const& user_password) const 580 +Encryption::check_user_password_V4(std::string const& user_password) const
474 { 581 {
475 // Algorithm 3.6 from the PDF 1.7 Reference Manual 582 // Algorithm 3.6 from the PDF 1.7 Reference Manual
476 583
@@ -480,7 +587,7 @@ QPDF::EncryptionData::check_user_password_V4(std::string const&amp; user_password) c @@ -480,7 +587,7 @@ QPDF::EncryptionData::check_user_password_V4(std::string const&amp; user_password) c
480 } 587 }
481 588
482 bool 589 bool
483 -QPDF::EncryptionData::check_user_password_V5(std::string const& user_password) const 590 +Encryption::check_user_password_V5(std::string const& user_password) const
484 { 591 {
485 // Algorithm 3.11 from the PDF 1.7 extension level 3 592 // Algorithm 3.11 from the PDF 1.7 extension level 3
486 593
@@ -491,7 +598,7 @@ QPDF::EncryptionData::check_user_password_V5(std::string const&amp; user_password) c @@ -491,7 +598,7 @@ QPDF::EncryptionData::check_user_password_V5(std::string const&amp; user_password) c
491 } 598 }
492 599
493 bool 600 bool
494 -QPDF::EncryptionData::check_user_password(std::string const& user_password) const 601 +Encryption::check_user_password(std::string const& user_password) const
495 { 602 {
496 if (getV() < 5) { 603 if (getV() < 5) {
497 return check_user_password_V4(user_password); 604 return check_user_password_V4(user_password);
@@ -501,7 +608,7 @@ QPDF::EncryptionData::check_user_password(std::string const&amp; user_password) cons @@ -501,7 +608,7 @@ QPDF::EncryptionData::check_user_password(std::string const&amp; user_password) cons
501 } 608 }
502 609
503 bool 610 bool
504 -QPDF::EncryptionData::check_owner_password_V4( 611 +Encryption::check_owner_password_V4(
505 std::string& user_password, std::string const& owner_password) const 612 std::string& user_password, std::string const& owner_password) const
506 { 613 {
507 // Algorithm 3.7 from the PDF 1.7 Reference Manual 614 // Algorithm 3.7 from the PDF 1.7 Reference Manual
@@ -518,7 +625,7 @@ QPDF::EncryptionData::check_owner_password_V4( @@ -518,7 +625,7 @@ QPDF::EncryptionData::check_owner_password_V4(
518 } 625 }
519 626
520 bool 627 bool
521 -QPDF::EncryptionData::check_owner_password_V5(std::string const& owner_password) const 628 +Encryption::check_owner_password_V5(std::string const& owner_password) const
522 { 629 {
523 // Algorithm 3.12 from the PDF 1.7 extension level 3 630 // Algorithm 3.12 from the PDF 1.7 extension level 3
524 631
@@ -529,7 +636,7 @@ QPDF::EncryptionData::check_owner_password_V5(std::string const&amp; owner_password) @@ -529,7 +636,7 @@ QPDF::EncryptionData::check_owner_password_V5(std::string const&amp; owner_password)
529 } 636 }
530 637
531 bool 638 bool
532 -QPDF::EncryptionData::check_owner_password( 639 +Encryption::check_owner_password(
533 std::string& user_password, std::string const& owner_password) const 640 std::string& user_password, std::string const& owner_password) const
534 { 641 {
535 if (getV() < 5) { 642 if (getV() < 5) {
@@ -540,7 +647,7 @@ QPDF::EncryptionData::check_owner_password( @@ -540,7 +647,7 @@ QPDF::EncryptionData::check_owner_password(
540 } 647 }
541 648
542 std::string 649 std::string
543 -QPDF::EncryptionData::recover_encryption_key_with_password(std::string const& password) const 650 +Encryption::recover_encryption_key_with_password(std::string const& password) const
544 { 651 {
545 // Disregard whether Perms is valid. 652 // Disregard whether Perms is valid.
546 bool disregard; 653 bool disregard;
@@ -548,7 +655,7 @@ QPDF::EncryptionData::recover_encryption_key_with_password(std::string const&amp; pa @@ -548,7 +655,7 @@ QPDF::EncryptionData::recover_encryption_key_with_password(std::string const&amp; pa
548 } 655 }
549 656
550 std::string 657 std::string
551 -QPDF::EncryptionData::compute_Perms_value_V5_clear() const 658 +Encryption::compute_Perms_value_V5_clear() const
552 { 659 {
553 // From algorithm 3.10 from the PDF 1.7 extension level 3 660 // From algorithm 3.10 from the PDF 1.7 extension level 3
554 std::string k = " \xff\xff\xff\xffTadb "; 661 std::string k = " \xff\xff\xff\xffTadb ";
@@ -565,7 +672,7 @@ QPDF::EncryptionData::compute_Perms_value_V5_clear() const @@ -565,7 +672,7 @@ QPDF::EncryptionData::compute_Perms_value_V5_clear() const
565 } 672 }
566 673
567 std::string 674 std::string
568 -QPDF::EncryptionData::recover_encryption_key_with_password( 675 +Encryption::recover_encryption_key_with_password(
569 std::string const& password, bool& perms_valid) const 676 std::string const& password, bool& perms_valid) const
570 { 677 {
571 // Algorithm 3.2a from the PDF 1.7 extension level 3 678 // Algorithm 3.2a from the PDF 1.7 extension level 3
@@ -795,7 +902,7 @@ QPDF::EncryptionParameters::initialize(QPDF&amp; qpdf) @@ -795,7 +902,7 @@ QPDF::EncryptionParameters::initialize(QPDF&amp; qpdf)
795 } 902 }
796 } 903 }
797 904
798 - EncryptionData data(V, R, Length / 8, p, O, U, OE, UE, Perms, id1, encrypt_metadata); 905 + Encryption data(V, R, Length / 8, p, O, U, OE, UE, Perms, id1, encrypt_metadata);
799 if (qm.provided_password_is_hex_key) { 906 if (qm.provided_password_is_hex_key) {
800 // ignore passwords in file 907 // ignore passwords in file
801 encryption_key = QUtil::hex_decode(provided_password); 908 encryption_key = QUtil::hex_decode(provided_password);
@@ -1023,14 +1130,14 @@ QPDF::compute_encryption_O_U( @@ -1023,14 +1130,14 @@ QPDF::compute_encryption_O_U(
1023 std::string& out_O, 1130 std::string& out_O,
1024 std::string& out_U) 1131 std::string& out_U)
1025 { 1132 {
1026 - EncryptionData data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata); 1133 + Encryption data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata);
1027 data.compute_encryption_O_U(user_password, owner_password); 1134 data.compute_encryption_O_U(user_password, owner_password);
1028 out_O = data.getO(); 1135 out_O = data.getO();
1029 out_U = data.getU(); 1136 out_U = data.getU();
1030 } 1137 }
1031 1138
1032 void 1139 void
1033 -QPDF::EncryptionData::compute_encryption_O_U(char const* user_password, char const* owner_password) 1140 +Encryption::compute_encryption_O_U(char const* user_password, char const* owner_password)
1034 { 1141 {
1035 if (V >= 5) { 1142 if (V >= 5) {
1036 throw std::logic_error("compute_encryption_O_U called for file with V >= 5"); 1143 throw std::logic_error("compute_encryption_O_U called for file with V >= 5");
@@ -1056,7 +1163,7 @@ QPDF::compute_encryption_parameters_V5( @@ -1056,7 +1163,7 @@ QPDF::compute_encryption_parameters_V5(
1056 std::string& out_UE, 1163 std::string& out_UE,
1057 std::string& out_Perms) 1164 std::string& out_Perms)
1058 { 1165 {
1059 - EncryptionData data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata); 1166 + Encryption data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata);
1060 encryption_key = data.compute_encryption_parameters_V5(user_password, owner_password); 1167 encryption_key = data.compute_encryption_parameters_V5(user_password, owner_password);
1061 1168
1062 out_O = data.getO(); 1169 out_O = data.getO();
@@ -1067,8 +1174,7 @@ QPDF::compute_encryption_parameters_V5( @@ -1067,8 +1174,7 @@ QPDF::compute_encryption_parameters_V5(
1067 } 1174 }
1068 1175
1069 std::string 1176 std::string
1070 -QPDF::EncryptionData::compute_encryption_parameters_V5(  
1071 - char const* user_password, char const* owner_password) 1177 +Encryption::compute_encryption_parameters_V5(char const* user_password, char const* owner_password)
1072 { 1178 {
1073 auto out_encryption_key = util::random_string(key_bytes); 1179 auto out_encryption_key = util::random_string(key_bytes);
1074 // Algorithm 8 from the PDF 2.0 1180 // Algorithm 8 from the PDF 2.0
@@ -1089,7 +1195,7 @@ QPDF::EncryptionData::compute_encryption_parameters_V5( @@ -1089,7 +1195,7 @@ QPDF::EncryptionData::compute_encryption_parameters_V5(
1089 } 1195 }
1090 1196
1091 std::string 1197 std::string
1092 -QPDF::EncryptionData::compute_parameters(char const* user_password, char const* owner_password) 1198 +Encryption::compute_parameters(char const* user_password, char const* owner_password)
1093 { 1199 {
1094 if (V < 5) { 1200 if (V < 5) {
1095 compute_encryption_O_U(user_password, owner_password); 1201 compute_encryption_O_U(user_password, owner_password);
libqpdf/qpdf/QPDF_private.hh
@@ -338,6 +338,123 @@ class QPDF::Doc @@ -338,6 +338,123 @@ class QPDF::Doc
338 class Streams; 338 class Streams;
339 class Writer; 339 class Writer;
340 340
  341 + class Encryption
  342 + {
  343 + public:
  344 + // This class holds data read from the encryption dictionary.
  345 + Encryption(
  346 + int V,
  347 + int R,
  348 + int Length_bytes,
  349 + int P,
  350 + std::string const& O,
  351 + std::string const& U,
  352 + std::string const& OE,
  353 + std::string const& UE,
  354 + std::string const& Perms,
  355 + std::string const& id1,
  356 + bool encrypt_metadata) :
  357 + V(V),
  358 + R(R),
  359 + Length_bytes(Length_bytes),
  360 + P(static_cast<unsigned long long>(P)),
  361 + O(O),
  362 + U(U),
  363 + OE(OE),
  364 + UE(UE),
  365 + Perms(Perms),
  366 + id1(id1),
  367 + encrypt_metadata(encrypt_metadata)
  368 + {
  369 + }
  370 + Encryption(int V, int R, int Length_bytes, bool encrypt_metadata) :
  371 + V(V),
  372 + R(R),
  373 + Length_bytes(Length_bytes),
  374 + encrypt_metadata(encrypt_metadata)
  375 + {
  376 + }
  377 +
  378 + int getV() const;
  379 + int getR() const;
  380 + int getLengthBytes() const;
  381 + int getP() const;
  382 + // Bits in P are numbered from 1 as in the PDF spec.
  383 + bool getP(size_t bit) const;
  384 + std::string const& getO() const;
  385 + std::string const& getU() const;
  386 + std::string const& getOE() const;
  387 + std::string const& getUE() const;
  388 + std::string const& getPerms() const;
  389 + std::string const& getId1() const;
  390 + bool getEncryptMetadata() const;
  391 + // Bits in P are numbered from 1 as in the PDF spec.
  392 + void setP(size_t bit, bool val);
  393 + void setP(unsigned long val);
  394 + void setO(std::string const&);
  395 + void setU(std::string const&);
  396 + void setId1(std::string const& val);
  397 + void setV5EncryptionParameters(
  398 + std::string const& O,
  399 + std::string const& OE,
  400 + std::string const& U,
  401 + std::string const& UE,
  402 + std::string const& Perms);
  403 +
  404 + std::string compute_encryption_key(std::string const& password) const;
  405 +
  406 + bool
  407 + check_owner_password(std::string& user_password, std::string const& owner_password) const;
  408 +
  409 + bool check_user_password(std::string const& user_password) const;
  410 +
  411 + std::string
  412 + recover_encryption_key_with_password(std::string const& password, bool& perms_valid) const;
  413 +
  414 + void compute_encryption_O_U(char const* user_password, char const* owner_password);
  415 +
  416 + std::string
  417 + compute_encryption_parameters_V5(char const* user_password, char const* owner_password);
  418 +
  419 + std::string compute_parameters(char const* user_password, char const* owner_password);
  420 +
  421 + private:
  422 + static constexpr unsigned int OU_key_bytes_V4 = 16; // ( == sizeof(MD5::Digest)
  423 +
  424 + Encryption(Encryption const&) = delete;
  425 + Encryption& operator=(Encryption const&) = delete;
  426 +
  427 + std::string hash_V5(
  428 + std::string const& password, std::string const& salt, std::string const& udata) const;
  429 + std::string
  430 + compute_O_value(std::string const& user_password, std::string const& owner_password) const;
  431 + std::string compute_U_value(std::string const& user_password) const;
  432 + std::string compute_encryption_key_from_password(std::string const& password) const;
  433 + std::string recover_encryption_key_with_password(std::string const& password) const;
  434 + bool check_owner_password_V4(
  435 + std::string& user_password, std::string const& owner_password) const;
  436 + bool check_owner_password_V5(std::string const& owner_passworda) const;
  437 + std::string compute_Perms_value_V5_clear() const;
  438 + std::string compute_O_rc4_key(
  439 + std::string const& user_password, std::string const& owner_password) const;
  440 + std::string compute_U_value_R2(std::string const& user_password) const;
  441 + std::string compute_U_value_R3(std::string const& user_password) const;
  442 + bool check_user_password_V4(std::string const& user_password) const;
  443 + bool check_user_password_V5(std::string const& user_password) const;
  444 +
  445 + int V;
  446 + int R;
  447 + int Length_bytes;
  448 + std::bitset<32> P{0xfffffffc}; // Specification always requires bits 1 and 2 to be cleared.
  449 + std::string O;
  450 + std::string U;
  451 + std::string OE;
  452 + std::string UE;
  453 + std::string Perms;
  454 + std::string id1;
  455 + bool encrypt_metadata;
  456 + };
  457 +
341 // StreamCopier class is restricted to QPDFObjectHandle so it can copy stream data. 458 // StreamCopier class is restricted to QPDFObjectHandle so it can copy stream data.
342 class StreamCopier 459 class StreamCopier
343 { 460 {