Commit d6ce922e4f03fd32940ce22f59997ffdc4f39100
1 parent
070b38bf
Refactor `QPDF::EncryptionData`: move to private `QPDF::Doc::Encryption` and update references.
Showing
4 changed files
with
276 additions
and
101 deletions
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& qpdf) | @@ -1094,7 +1096,7 @@ QPDFWriter::Members::copyEncryptionParameters(QPDF& 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& password) const | @@ -378,7 +485,7 @@ QPDF::EncryptionData::compute_encryption_key(std::string const& 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& pa | @@ -405,7 +512,7 @@ QPDF::EncryptionData::compute_encryption_key_from_password(std::string const& 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& user_password) const | @@ -443,7 +550,7 @@ QPDF::EncryptionData::compute_U_value_R2(std::string const& 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& user_password) const | @@ -460,7 +567,7 @@ QPDF::EncryptionData::compute_U_value_R3(std::string const& 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& user_password) const | @@ -470,7 +577,7 @@ QPDF::EncryptionData::compute_U_value(std::string const& 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& user_password) c | @@ -480,7 +587,7 @@ QPDF::EncryptionData::check_user_password_V4(std::string const& 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& user_password) c | @@ -491,7 +598,7 @@ QPDF::EncryptionData::check_user_password_V5(std::string const& 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& user_password) cons | @@ -501,7 +608,7 @@ QPDF::EncryptionData::check_user_password(std::string const& 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& owner_password) | @@ -529,7 +636,7 @@ QPDF::EncryptionData::check_owner_password_V5(std::string const& 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& pa | @@ -548,7 +655,7 @@ QPDF::EncryptionData::recover_encryption_key_with_password(std::string const& 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& qpdf) | @@ -795,7 +902,7 @@ QPDF::EncryptionParameters::initialize(QPDF& 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 | { |