Commit 68447bb556364efefc41a3af72a9455b6e43c137
1 parent
04c203ae
change EncryptionData
Showing
2 changed files
with
107 additions
and
24 deletions
include/qpdf/QPDF.hh
| @@ -223,8 +223,10 @@ class QPDF | @@ -223,8 +223,10 @@ class QPDF | ||
| 223 | // Encryption support | 223 | // Encryption support |
| 224 | 224 | ||
| 225 | enum encryption_method_e { e_none, e_unknown, e_rc4, e_aes }; | 225 | enum encryption_method_e { e_none, e_unknown, e_rc4, e_aes }; |
| 226 | - struct EncryptionData | 226 | + class EncryptionData |
| 227 | { | 227 | { |
| 228 | + public: | ||
| 229 | + | ||
| 228 | // This class holds data read from the encryption dictionary. | 230 | // This class holds data read from the encryption dictionary. |
| 229 | EncryptionData(int V, int R, int Length_bytes, int P, | 231 | EncryptionData(int V, int R, int Length_bytes, int P, |
| 230 | std::string const& O, std::string const& U, | 232 | std::string const& O, std::string const& U, |
| @@ -240,6 +242,22 @@ class QPDF | @@ -240,6 +242,22 @@ class QPDF | ||
| 240 | { | 242 | { |
| 241 | } | 243 | } |
| 242 | 244 | ||
| 245 | + int getV() const; | ||
| 246 | + int getR() const; | ||
| 247 | + int getLengthBytes() const; | ||
| 248 | + int getP() const; | ||
| 249 | + std::string const& getO() const; | ||
| 250 | + std::string const& getU() const; | ||
| 251 | + std::string const& getId1() const; | ||
| 252 | + bool getEncryptMetadata() const; | ||
| 253 | + | ||
| 254 | + void setO(std::string const&); | ||
| 255 | + void setU(std::string const&); | ||
| 256 | + | ||
| 257 | + private: | ||
| 258 | + EncryptionData(EncryptionData const&); | ||
| 259 | + EncryptionData& operator=(EncryptionData const&); | ||
| 260 | + | ||
| 243 | int V; | 261 | int V; |
| 244 | int R; | 262 | int R; |
| 245 | int Length_bytes; | 263 | int Length_bytes; |
libqpdf/QPDF_encryption.cc
| @@ -26,7 +26,67 @@ static unsigned char const padding_string[] = { | @@ -26,7 +26,67 @@ static unsigned char const padding_string[] = { | ||
| 26 | static unsigned int const O_key_bytes = sizeof(MD5::Digest); | 26 | static unsigned int const O_key_bytes = sizeof(MD5::Digest); |
| 27 | static unsigned int const key_bytes = 32; | 27 | static unsigned int const key_bytes = 32; |
| 28 | 28 | ||
| 29 | +int | ||
| 30 | +QPDF::EncryptionData::getV() const | ||
| 31 | +{ | ||
| 32 | + return this->V; | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +int | ||
| 36 | +QPDF::EncryptionData::getR() const | ||
| 37 | +{ | ||
| 38 | + return this->R; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +int | ||
| 42 | +QPDF::EncryptionData::getLengthBytes() const | ||
| 43 | +{ | ||
| 44 | + return this->Length_bytes; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +int | ||
| 48 | +QPDF::EncryptionData::getP() const | ||
| 49 | +{ | ||
| 50 | + return this->P; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +std::string const& | ||
| 54 | +QPDF::EncryptionData::getO() const | ||
| 55 | +{ | ||
| 56 | + return this->O; | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +std::string const& | ||
| 60 | +QPDF::EncryptionData::getU() const | ||
| 61 | +{ | ||
| 62 | + return this->U; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +std::string const& | ||
| 66 | +QPDF::EncryptionData::getId1() const | ||
| 67 | +{ | ||
| 68 | + return this->id1; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +bool | ||
| 72 | +QPDF::EncryptionData::getEncryptMetadata() const | ||
| 73 | +{ | ||
| 74 | + return this->encrypt_metadata; | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +void | ||
| 78 | +QPDF::EncryptionData::setO(std::string const& O) | ||
| 79 | +{ | ||
| 80 | + this->O = O; | ||
| 81 | +} | ||
| 82 | + | ||
| 29 | void | 83 | void |
| 84 | +QPDF::EncryptionData::setU(std::string const& U) | ||
| 85 | +{ | ||
| 86 | + this->U = U; | ||
| 87 | +} | ||
| 88 | + | ||
| 89 | +static void | ||
| 30 | pad_or_truncate_password(std::string const& password, char k1[key_bytes]) | 90 | pad_or_truncate_password(std::string const& password, char k1[key_bytes]) |
| 31 | { | 91 | { |
| 32 | int password_bytes = std::min(key_bytes, (unsigned int)password.length()); | 92 | int password_bytes = std::min(key_bytes, (unsigned int)password.length()); |
| @@ -137,23 +197,25 @@ QPDF::compute_encryption_key( | @@ -137,23 +197,25 @@ QPDF::compute_encryption_key( | ||
| 137 | MD5 md5; | 197 | MD5 md5; |
| 138 | md5.encodeDataIncrementally( | 198 | md5.encodeDataIncrementally( |
| 139 | pad_or_truncate_password(password).c_str(), key_bytes); | 199 | pad_or_truncate_password(password).c_str(), key_bytes); |
| 140 | - md5.encodeDataIncrementally(data.O.c_str(), key_bytes); | 200 | + md5.encodeDataIncrementally(data.getO().c_str(), key_bytes); |
| 141 | char pbytes[4]; | 201 | char pbytes[4]; |
| 142 | - pbytes[0] = (char) (data.P & 0xff); | ||
| 143 | - pbytes[1] = (char) ((data.P >> 8) & 0xff); | ||
| 144 | - pbytes[2] = (char) ((data.P >> 16) & 0xff); | ||
| 145 | - pbytes[3] = (char) ((data.P >> 24) & 0xff); | 202 | + int P = data.getP(); |
| 203 | + pbytes[0] = (char) (P & 0xff); | ||
| 204 | + pbytes[1] = (char) ((P >> 8) & 0xff); | ||
| 205 | + pbytes[2] = (char) ((P >> 16) & 0xff); | ||
| 206 | + pbytes[3] = (char) ((P >> 24) & 0xff); | ||
| 146 | md5.encodeDataIncrementally(pbytes, 4); | 207 | md5.encodeDataIncrementally(pbytes, 4); |
| 147 | - md5.encodeDataIncrementally(data.id1.c_str(), (int)data.id1.length()); | ||
| 148 | - if ((data.R >= 4) && (! data.encrypt_metadata)) | 208 | + md5.encodeDataIncrementally(data.getId1().c_str(), |
| 209 | + (int)data.getId1().length()); | ||
| 210 | + if ((data.getR() >= 4) && (! data.getEncryptMetadata())) | ||
| 149 | { | 211 | { |
| 150 | char bytes[4]; | 212 | char bytes[4]; |
| 151 | memset(bytes, 0xff, 4); | 213 | memset(bytes, 0xff, 4); |
| 152 | md5.encodeDataIncrementally(bytes, 4); | 214 | md5.encodeDataIncrementally(bytes, 4); |
| 153 | } | 215 | } |
| 154 | MD5::Digest digest; | 216 | MD5::Digest digest; |
| 155 | - iterate_md5_digest(md5, digest, ((data.R >= 3) ? 50 : 0)); | ||
| 156 | - return std::string((char*)digest, data.Length_bytes); | 217 | + iterate_md5_digest(md5, digest, ((data.getR() >= 3) ? 50 : 0)); |
| 218 | + return std::string((char*)digest, data.getLengthBytes()); | ||
| 157 | } | 219 | } |
| 158 | 220 | ||
| 159 | static void | 221 | static void |
| @@ -171,7 +233,7 @@ compute_O_rc4_key(std::string const& user_password, | @@ -171,7 +233,7 @@ compute_O_rc4_key(std::string const& user_password, | ||
| 171 | md5.encodeDataIncrementally( | 233 | md5.encodeDataIncrementally( |
| 172 | pad_or_truncate_password(password).c_str(), key_bytes); | 234 | pad_or_truncate_password(password).c_str(), key_bytes); |
| 173 | MD5::Digest digest; | 235 | MD5::Digest digest; |
| 174 | - iterate_md5_digest(md5, digest, ((data.R >= 3) ? 50 : 0)); | 236 | + iterate_md5_digest(md5, digest, ((data.getR() >= 3) ? 50 : 0)); |
| 175 | memcpy(key, digest, O_key_bytes); | 237 | memcpy(key, digest, O_key_bytes); |
| 176 | } | 238 | } |
| 177 | 239 | ||
| @@ -188,7 +250,8 @@ compute_O_value(std::string const& user_password, | @@ -188,7 +250,8 @@ compute_O_value(std::string const& user_password, | ||
| 188 | char upass[key_bytes]; | 250 | char upass[key_bytes]; |
| 189 | pad_or_truncate_password(user_password, upass); | 251 | pad_or_truncate_password(user_password, upass); |
| 190 | iterate_rc4((unsigned char*) upass, key_bytes, | 252 | iterate_rc4((unsigned char*) upass, key_bytes, |
| 191 | - O_key, data.Length_bytes, (data.R >= 3) ? 20 : 1, false); | 253 | + O_key, data.getLengthBytes(), |
| 254 | + (data.getR() >= 3) ? 20 : 1, false); | ||
| 192 | return std::string(upass, key_bytes); | 255 | return std::string(upass, key_bytes); |
| 193 | } | 256 | } |
| 194 | 257 | ||
| @@ -203,7 +266,7 @@ compute_U_value_R2(std::string const& user_password, | @@ -203,7 +266,7 @@ compute_U_value_R2(std::string const& user_password, | ||
| 203 | char udata[key_bytes]; | 266 | char udata[key_bytes]; |
| 204 | pad_or_truncate_password("", udata); | 267 | pad_or_truncate_password("", udata); |
| 205 | iterate_rc4((unsigned char*) udata, key_bytes, | 268 | iterate_rc4((unsigned char*) udata, key_bytes, |
| 206 | - (unsigned char*)k1.c_str(), data.Length_bytes, 1, false); | 269 | + (unsigned char*)k1.c_str(), data.getLengthBytes(), 1, false); |
| 207 | return std::string(udata, key_bytes); | 270 | return std::string(udata, key_bytes); |
| 208 | } | 271 | } |
| 209 | 272 | ||
| @@ -218,11 +281,12 @@ compute_U_value_R3(std::string const& user_password, | @@ -218,11 +281,12 @@ compute_U_value_R3(std::string const& user_password, | ||
| 218 | MD5 md5; | 281 | MD5 md5; |
| 219 | md5.encodeDataIncrementally( | 282 | md5.encodeDataIncrementally( |
| 220 | pad_or_truncate_password("").c_str(), key_bytes); | 283 | pad_or_truncate_password("").c_str(), key_bytes); |
| 221 | - md5.encodeDataIncrementally(data.id1.c_str(), (int)data.id1.length()); | 284 | + md5.encodeDataIncrementally(data.getId1().c_str(), |
| 285 | + (int)data.getId1().length()); | ||
| 222 | MD5::Digest digest; | 286 | MD5::Digest digest; |
| 223 | md5.digest(digest); | 287 | md5.digest(digest); |
| 224 | iterate_rc4(digest, sizeof(MD5::Digest), | 288 | iterate_rc4(digest, sizeof(MD5::Digest), |
| 225 | - (unsigned char*) k1.c_str(), data.Length_bytes, 20, false); | 289 | + (unsigned char*) k1.c_str(), data.getLengthBytes(), 20, false); |
| 226 | char result[key_bytes]; | 290 | char result[key_bytes]; |
| 227 | memcpy(result, digest, sizeof(MD5::Digest)); | 291 | memcpy(result, digest, sizeof(MD5::Digest)); |
| 228 | // pad with arbitrary data -- make it consistent for the sake of | 292 | // pad with arbitrary data -- make it consistent for the sake of |
| @@ -238,7 +302,7 @@ static std::string | @@ -238,7 +302,7 @@ static std::string | ||
| 238 | compute_U_value(std::string const& user_password, | 302 | compute_U_value(std::string const& user_password, |
| 239 | QPDF::EncryptionData const& data) | 303 | QPDF::EncryptionData const& data) |
| 240 | { | 304 | { |
| 241 | - if (data.R >= 3) | 305 | + if (data.getR() >= 3) |
| 242 | { | 306 | { |
| 243 | return compute_U_value_R3(user_password, data); | 307 | return compute_U_value_R3(user_password, data); |
| 244 | } | 308 | } |
| @@ -253,8 +317,8 @@ check_user_password(std::string const& user_password, | @@ -253,8 +317,8 @@ check_user_password(std::string const& user_password, | ||
| 253 | // Algorithm 3.6 from the PDF 1.7 Reference Manual | 317 | // Algorithm 3.6 from the PDF 1.7 Reference Manual |
| 254 | 318 | ||
| 255 | std::string u_value = compute_U_value(user_password, data); | 319 | std::string u_value = compute_U_value(user_password, data); |
| 256 | - int to_compare = ((data.R >= 3) ? sizeof(MD5::Digest) : key_bytes); | ||
| 257 | - return (memcmp(data.U.c_str(), u_value.c_str(), to_compare) == 0); | 320 | + int to_compare = ((data.getR() >= 3) ? sizeof(MD5::Digest) : key_bytes); |
| 321 | + return (memcmp(data.getU().c_str(), u_value.c_str(), to_compare) == 0); | ||
| 258 | } | 322 | } |
| 259 | 323 | ||
| 260 | static bool | 324 | static bool |
| @@ -267,9 +331,9 @@ check_owner_password(std::string& user_password, | @@ -267,9 +331,9 @@ check_owner_password(std::string& user_password, | ||
| 267 | unsigned char key[O_key_bytes]; | 331 | unsigned char key[O_key_bytes]; |
| 268 | compute_O_rc4_key(user_password, owner_password, data, key); | 332 | compute_O_rc4_key(user_password, owner_password, data, key); |
| 269 | unsigned char O_data[key_bytes]; | 333 | unsigned char O_data[key_bytes]; |
| 270 | - memcpy(O_data, (unsigned char*) data.O.c_str(), key_bytes); | ||
| 271 | - iterate_rc4(O_data, key_bytes, key, data.Length_bytes, | ||
| 272 | - (data.R >= 3) ? 20 : 1, true); | 334 | + memcpy(O_data, (unsigned char*) data.getO().c_str(), key_bytes); |
| 335 | + iterate_rc4(O_data, key_bytes, key, data.getLengthBytes(), | ||
| 336 | + (data.getR() >= 3) ? 20 : 1, true); | ||
| 273 | std::string new_user_password = | 337 | std::string new_user_password = |
| 274 | std::string((char*)O_data, key_bytes); | 338 | std::string((char*)O_data, key_bytes); |
| 275 | bool result = false; | 339 | bool result = false; |
| @@ -716,9 +780,10 @@ QPDF::compute_encryption_O_U( | @@ -716,9 +780,10 @@ QPDF::compute_encryption_O_U( | ||
| 716 | std::string const& id1, std::string& O, std::string& U) | 780 | std::string const& id1, std::string& O, std::string& U) |
| 717 | { | 781 | { |
| 718 | EncryptionData data(V, R, key_len, P, "", "", id1, encrypt_metadata); | 782 | EncryptionData data(V, R, key_len, P, "", "", id1, encrypt_metadata); |
| 719 | - data.O = compute_O_value(user_password, owner_password, data); | ||
| 720 | - O = data.O; | ||
| 721 | - U = compute_U_value(user_password, data); | 783 | + data.setO(compute_O_value(user_password, owner_password, data)); |
| 784 | + O = data.getO(); | ||
| 785 | + data.setU(compute_U_value(user_password, data)); | ||
| 786 | + U = data.getU(); | ||
| 722 | } | 787 | } |
| 723 | 788 | ||
| 724 | std::string const& | 789 | std::string const& |