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 | 223 | // Encryption support |
| 224 | 224 | |
| 225 | 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 | 230 | // This class holds data read from the encryption dictionary. |
| 229 | 231 | EncryptionData(int V, int R, int Length_bytes, int P, |
| 230 | 232 | std::string const& O, std::string const& U, |
| ... | ... | @@ -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 | 261 | int V; |
| 244 | 262 | int R; |
| 245 | 263 | int Length_bytes; | ... | ... |
libqpdf/QPDF_encryption.cc
| ... | ... | @@ -26,7 +26,67 @@ static unsigned char const padding_string[] = { |
| 26 | 26 | static unsigned int const O_key_bytes = sizeof(MD5::Digest); |
| 27 | 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 | 83 | void |
| 84 | +QPDF::EncryptionData::setU(std::string const& U) | |
| 85 | +{ | |
| 86 | + this->U = U; | |
| 87 | +} | |
| 88 | + | |
| 89 | +static void | |
| 30 | 90 | pad_or_truncate_password(std::string const& password, char k1[key_bytes]) |
| 31 | 91 | { |
| 32 | 92 | int password_bytes = std::min(key_bytes, (unsigned int)password.length()); |
| ... | ... | @@ -137,23 +197,25 @@ QPDF::compute_encryption_key( |
| 137 | 197 | MD5 md5; |
| 138 | 198 | md5.encodeDataIncrementally( |
| 139 | 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 | 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 | 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 | 212 | char bytes[4]; |
| 151 | 213 | memset(bytes, 0xff, 4); |
| 152 | 214 | md5.encodeDataIncrementally(bytes, 4); |
| 153 | 215 | } |
| 154 | 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 | 221 | static void |
| ... | ... | @@ -171,7 +233,7 @@ compute_O_rc4_key(std::string const& user_password, |
| 171 | 233 | md5.encodeDataIncrementally( |
| 172 | 234 | pad_or_truncate_password(password).c_str(), key_bytes); |
| 173 | 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 | 237 | memcpy(key, digest, O_key_bytes); |
| 176 | 238 | } |
| 177 | 239 | |
| ... | ... | @@ -188,7 +250,8 @@ compute_O_value(std::string const& user_password, |
| 188 | 250 | char upass[key_bytes]; |
| 189 | 251 | pad_or_truncate_password(user_password, upass); |
| 190 | 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 | 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 | 266 | char udata[key_bytes]; |
| 204 | 267 | pad_or_truncate_password("", udata); |
| 205 | 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 | 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 | 281 | MD5 md5; |
| 219 | 282 | md5.encodeDataIncrementally( |
| 220 | 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 | 286 | MD5::Digest digest; |
| 223 | 287 | md5.digest(digest); |
| 224 | 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 | 290 | char result[key_bytes]; |
| 227 | 291 | memcpy(result, digest, sizeof(MD5::Digest)); |
| 228 | 292 | // pad with arbitrary data -- make it consistent for the sake of |
| ... | ... | @@ -238,7 +302,7 @@ static std::string |
| 238 | 302 | compute_U_value(std::string const& user_password, |
| 239 | 303 | QPDF::EncryptionData const& data) |
| 240 | 304 | { |
| 241 | - if (data.R >= 3) | |
| 305 | + if (data.getR() >= 3) | |
| 242 | 306 | { |
| 243 | 307 | return compute_U_value_R3(user_password, data); |
| 244 | 308 | } |
| ... | ... | @@ -253,8 +317,8 @@ check_user_password(std::string const& user_password, |
| 253 | 317 | // Algorithm 3.6 from the PDF 1.7 Reference Manual |
| 254 | 318 | |
| 255 | 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 | 324 | static bool |
| ... | ... | @@ -267,9 +331,9 @@ check_owner_password(std::string& user_password, |
| 267 | 331 | unsigned char key[O_key_bytes]; |
| 268 | 332 | compute_O_rc4_key(user_password, owner_password, data, key); |
| 269 | 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 | 337 | std::string new_user_password = |
| 274 | 338 | std::string((char*)O_data, key_bytes); |
| 275 | 339 | bool result = false; |
| ... | ... | @@ -716,9 +780,10 @@ QPDF::compute_encryption_O_U( |
| 716 | 780 | std::string const& id1, std::string& O, std::string& U) |
| 717 | 781 | { |
| 718 | 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 | 789 | std::string const& | ... | ... |