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 472 V(V),
473 473 R(R),
474 474 Length_bytes(Length_bytes),
475   - P(static_cast<unsigned long long>(P)),
  475 + P(P),
476 476 O(O),
477 477 U(U),
478 478 OE(OE),
... ... @@ -482,20 +482,11 @@ class QPDF
482 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 486 int getV() const;
494 487 int getR() const;
495 488 int getLengthBytes() const;
496 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 490 std::string const& getO() const;
500 491 std::string const& getU() const;
501 492 std::string const& getOE() const;
... ... @@ -503,12 +494,9 @@ class QPDF
503 494 std::string const& getPerms() const;
504 495 std::string const& getId1() const;
505 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 498 void setO(std::string const&);
510 499 void setU(std::string const&);
511   - void setId1(std::string const& val);
512 500 void setV5EncryptionParameters(
513 501 std::string const& O,
514 502 std::string const& OE,
... ... @@ -516,51 +504,14 @@ class QPDF
516 504 std::string const& UE,
517 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 507 private:
537   - static constexpr unsigned int OU_key_bytes_V4 = 16; // ( == sizeof(MD5::Digest)
538   -
539 508 EncryptionData(EncryptionData const&) = delete;
540 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 511 int V;
561 512 int R;
562 513 int Length_bytes;
563   - std::bitset<32> P{0xfffffffc}; // Specification always requires bits 1 and 2 to be cleared.
  514 + int P;
564 515 std::string O;
565 516 std::string U;
566 517 std::string OE;
... ... @@ -569,7 +520,6 @@ class QPDF
569 520 std::string id1;
570 521 bool encrypt_metadata;
571 522 };
572   -
573 523 QPDF_DLL
574 524 bool isEncrypted() const;
575 525  
... ...
libqpdf/QPDFWriter.cc
... ... @@ -27,6 +27,8 @@
27 27 using namespace std::literals;
28 28 using namespace qpdf;
29 29  
  30 +using Encryption = QPDF::Doc::Encryption;
  31 +
30 32 QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default)
31 33 {
32 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 506 bool pclm{false};
505 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 510 std::string encryption_key;
509 511 bool encrypt_use_aes{false};
510 512  
... ... @@ -829,7 +831,7 @@ QPDFWriter::setR2EncryptionParametersInsecure(
829 831 bool allow_extract,
830 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 835 if (!allow_print) {
834 836 m->encryption->setP(3, false);
835 837 }
... ... @@ -857,7 +859,7 @@ QPDFWriter::setR3EncryptionParametersInsecure(
857 859 bool allow_modify_other,
858 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 863 m->interpretR3EncryptionParameters(
862 864 allow_accessibility,
863 865 allow_extract,
... ... @@ -884,7 +886,7 @@ QPDFWriter::setR4EncryptionParametersInsecure(
884 886 bool encrypt_metadata,
885 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 890 m->encrypt_use_aes = use_aes;
889 891 m->interpretR3EncryptionParameters(
890 892 allow_accessibility,
... ... @@ -911,7 +913,7 @@ QPDFWriter::setR5EncryptionParameters(
911 913 qpdf_r3_print_e print,
912 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 917 m->encrypt_use_aes = true;
916 918 m->interpretR3EncryptionParameters(
917 919 allow_accessibility,
... ... @@ -938,7 +940,7 @@ QPDFWriter::setR6EncryptionParameters(
938 940 qpdf_r3_print_e print,
939 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 944 m->interpretR3EncryptionParameters(
943 945 allow_accessibility,
944 946 allow_extract,
... ... @@ -1094,7 +1096,7 @@ QPDFWriter::Members::copyEncryptionParameters(QPDF&amp; qpdf)
1094 1096 QTC::TC("qpdf", "QPDFWriter copy encrypt metadata", encrypt_metadata ? 0 : 1);
1095 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 1100 V,
1099 1101 encrypt.getKey("/R").getIntValueAsInt(),
1100 1102 key_len,
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -21,6 +21,8 @@
21 21 using namespace qpdf;
22 22 using namespace std::literals;
23 23  
  24 +using Encryption = QPDF::Doc::Encryption;
  25 +
24 26 static std::string padding_string =
25 27 "\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56\xff\xfa\x01\x08"
26 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 54 int
53 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 150 return static_cast<int>(P.to_ulong());
56 151 }
57 152  
58 153 bool
59   -QPDF::EncryptionData::getP(size_t bit) const
  154 +Encryption::getP(size_t bit) const
60 155 {
61 156 qpdf_assert_debug(bit);
62 157 return P.test(bit - 1);
... ... @@ -70,80 +165,80 @@ QPDF::EncryptionParameters::P(size_t bit) const
70 165 }
71 166  
72 167 std::string const&
73   -QPDF::EncryptionData::getO() const
  168 +Encryption::getO() const
74 169 {
75 170 return this->O;
76 171 }
77 172  
78 173 std::string const&
79   -QPDF::EncryptionData::getU() const
  174 +Encryption::getU() const
80 175 {
81 176 return this->U;
82 177 }
83 178  
84 179 std::string const&
85   -QPDF::EncryptionData::getOE() const
  180 +Encryption::getOE() const
86 181 {
87 182 return this->OE;
88 183 }
89 184  
90 185 std::string const&
91   -QPDF::EncryptionData::getUE() const
  186 +Encryption::getUE() const
92 187 {
93 188 return this->UE;
94 189 }
95 190  
96 191 std::string const&
97   -QPDF::EncryptionData::getPerms() const
  192 +Encryption::getPerms() const
98 193 {
99 194 return this->Perms;
100 195 }
101 196  
102 197 std::string const&
103   -QPDF::EncryptionData::getId1() const
  198 +Encryption::getId1() const
104 199 {
105 200 return this->id1;
106 201 }
107 202  
108 203 bool
109   -QPDF::EncryptionData::getEncryptMetadata() const
  204 +Encryption::getEncryptMetadata() const
110 205 {
111 206 return this->encrypt_metadata;
112 207 }
113 208  
114 209 void
115   -QPDF::EncryptionData::setO(std::string const& O)
  210 +Encryption::setO(std::string const& O)
116 211 {
117 212 this->O = O;
118 213 }
119 214  
120 215 void
121   -QPDF::EncryptionData::setU(std::string const& U)
  216 +Encryption::setU(std::string const& U)
122 217 {
123 218 this->U = U;
124 219 }
125 220  
126 221 void
127   -QPDF::EncryptionData::setP(size_t bit, bool val)
  222 +Encryption::setP(size_t bit, bool val)
128 223 {
129 224 qpdf_assert_debug(bit);
130 225 P.set(bit - 1, val);
131 226 }
132 227  
133 228 void
134   -QPDF::EncryptionData::setP(unsigned long val)
  229 +Encryption::setP(unsigned long val)
135 230 {
136 231 P = std::bitset<32>(val);
137 232 }
138 233  
139 234 void
140   -QPDF::EncryptionData::setId1(std::string const& val)
  235 +Encryption::setId1(std::string const& val)
141 236 {
142 237 id1 = val;
143 238 }
144 239  
145 240 void
146   -QPDF::EncryptionData::setV5EncryptionParameters(
  241 +Encryption::setV5EncryptionParameters(
147 242 std::string const& O,
148 243 std::string const& OE,
149 244 std::string const& U,
... ... @@ -246,7 +341,7 @@ process_with_aes(
246 341 }
247 342  
248 343 std::string
249   -QPDF::EncryptionData::hash_V5(
  344 +Encryption::hash_V5(
250 345 std::string const& password, std::string const& salt, std::string const& udata) const
251 346 {
252 347 Pl_SHA2 hash(256);
... ... @@ -358,13 +453,25 @@ QPDF::compute_data_key(
358 453 }
359 454  
360 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 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 476 if (getV() >= 5) {
370 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 485 }
379 486  
380 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 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 512 }
406 513  
407 514 std::string
408   -QPDF::EncryptionData::compute_O_rc4_key(
  515 +Encryption::compute_O_rc4_key(
409 516 std::string const& user_password, std::string const& owner_password) const
410 517 {
411 518 if (getV() >= 5) {
... ... @@ -418,7 +525,7 @@ QPDF::EncryptionData::compute_O_rc4_key(
418 525 }
419 526  
420 527 std::string
421   -QPDF::EncryptionData::compute_O_value(
  528 +Encryption::compute_O_value(
422 529 std::string const& user_password, std::string const& owner_password) const
423 530 {
424 531 // Algorithm 3.3 from the PDF 1.7 Reference Manual
... ... @@ -431,7 +538,7 @@ QPDF::EncryptionData::compute_O_value(
431 538 }
432 539  
433 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 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 550 }
444 551  
445 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 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 567 }
461 568  
462 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 572 if (getR() >= 3) {
466 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 577 }
471 578  
472 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 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 587 }
481 588  
482 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 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 598 }
492 599  
493 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 603 if (getV() < 5) {
497 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 608 }
502 609  
503 610 bool
504   -QPDF::EncryptionData::check_owner_password_V4(
  611 +Encryption::check_owner_password_V4(
505 612 std::string& user_password, std::string const& owner_password) const
506 613 {
507 614 // Algorithm 3.7 from the PDF 1.7 Reference Manual
... ... @@ -518,7 +625,7 @@ QPDF::EncryptionData::check_owner_password_V4(
518 625 }
519 626  
520 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 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 636 }
530 637  
531 638 bool
532   -QPDF::EncryptionData::check_owner_password(
  639 +Encryption::check_owner_password(
533 640 std::string& user_password, std::string const& owner_password) const
534 641 {
535 642 if (getV() < 5) {
... ... @@ -540,7 +647,7 @@ QPDF::EncryptionData::check_owner_password(
540 647 }
541 648  
542 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 652 // Disregard whether Perms is valid.
546 653 bool disregard;
... ... @@ -548,7 +655,7 @@ QPDF::EncryptionData::recover_encryption_key_with_password(std::string const&amp; pa
548 655 }
549 656  
550 657 std::string
551   -QPDF::EncryptionData::compute_Perms_value_V5_clear() const
  658 +Encryption::compute_Perms_value_V5_clear() const
552 659 {
553 660 // From algorithm 3.10 from the PDF 1.7 extension level 3
554 661 std::string k = " \xff\xff\xff\xffTadb ";
... ... @@ -565,7 +672,7 @@ QPDF::EncryptionData::compute_Perms_value_V5_clear() const
565 672 }
566 673  
567 674 std::string
568   -QPDF::EncryptionData::recover_encryption_key_with_password(
  675 +Encryption::recover_encryption_key_with_password(
569 676 std::string const& password, bool& perms_valid) const
570 677 {
571 678 // Algorithm 3.2a from the PDF 1.7 extension level 3
... ... @@ -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 906 if (qm.provided_password_is_hex_key) {
800 907 // ignore passwords in file
801 908 encryption_key = QUtil::hex_decode(provided_password);
... ... @@ -1023,14 +1130,14 @@ QPDF::compute_encryption_O_U(
1023 1130 std::string& out_O,
1024 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 1134 data.compute_encryption_O_U(user_password, owner_password);
1028 1135 out_O = data.getO();
1029 1136 out_U = data.getU();
1030 1137 }
1031 1138  
1032 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 1142 if (V >= 5) {
1036 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 1163 std::string& out_UE,
1057 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 1167 encryption_key = data.compute_encryption_parameters_V5(user_password, owner_password);
1061 1168  
1062 1169 out_O = data.getO();
... ... @@ -1067,8 +1174,7 @@ QPDF::compute_encryption_parameters_V5(
1067 1174 }
1068 1175  
1069 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 1179 auto out_encryption_key = util::random_string(key_bytes);
1074 1180 // Algorithm 8 from the PDF 2.0
... ... @@ -1089,7 +1195,7 @@ QPDF::EncryptionData::compute_encryption_parameters_V5(
1089 1195 }
1090 1196  
1091 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 1200 if (V < 5) {
1095 1201 compute_encryption_O_U(user_password, owner_password);
... ...
libqpdf/qpdf/QPDF_private.hh
... ... @@ -338,6 +338,123 @@ class QPDF::Doc
338 338 class Streams;
339 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 458 // StreamCopier class is restricted to QPDFObjectHandle so it can copy stream data.
342 459 class StreamCopier
343 460 {
... ...