Skip to content

Commit 5776832

Browse files
nicoawesomekling
authored andcommitted
LibPDF: Implement 7.6.4.4.11 Algorithm 12: Authenticating owner password
...for handlers of revision 6. Since this adds U to the hash input, also trim the size of U and O to 48 bytes. The spec requires them to be 48 bytes, but all the newer PDFs on https://cipa.jp/e/std/std-sec.html have 127 bytes -- 48 real bytes and 79 nul padding bytes. These files were created by: Creator: Word 用 Acrobat PDFMaker 17 Producer: Adobe PDF Library 15.0 and Creator: Word 用 Acrobat PDFMaker 17 Producer: Adobe PDF Library 17.11.238
1 parent 8f6c67a commit 5776832

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

Userland/Libraries/LibPDF/Encryption.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,19 @@ PDFErrorOr<NonnullRefPtr<StandardSecurityHandler>> StandardSecurityHandler::crea
166166
if (encryption_dict->contains(CommonNames::EncryptMetadata))
167167
encryption_dict->get_value(CommonNames::EncryptMetadata).get<bool>();
168168

169+
if (v >= 5) {
170+
// O and U are 48 bytes for V == 5, but some files pad them with nul bytes to 127 bytes. So trim them, if necessary.
171+
if (o.length() > 48)
172+
o = o.substring(0, 48);
173+
if (u.length() > 48)
174+
u = u.substring(0, 48);
175+
176+
if (o.length() != 48)
177+
return Error(Error::Type::Parse, "Invalid O size");
178+
if (u.length() != 48)
179+
return Error(Error::Type::Parse, "Invalid U size");
180+
}
181+
169182
return adopt_ref(*new StandardSecurityHandler(document, revision, o, u, p, encrypt_metadata, length, method));
170183
}
171184

@@ -294,6 +307,24 @@ bool StandardSecurityHandler::authenticate_user_password_r6_and_later(StringView
294307
return hash == m_u_entry.bytes().trim(32);
295308
}
296309

310+
bool StandardSecurityHandler::authenticate_owner_password_r6_and_later(StringView password)
311+
{
312+
// ISO 32000 (PDF 2.0), 7.6.4.4.11 Algorithm 12: Authenticating the owner password (Security handlers of
313+
// revision 6)
314+
315+
// a) Test the password against the owner key by computing the 32-byte hash using algorithm 2.B with an
316+
// input string consisting of the UTF-8 password concatenated with the 8 bytes of Owner Validation Salt
317+
// and the 48 byte U string. If the 32- byte result matches the first 32 bytes of the O string, this is the owner
318+
// password.
319+
ByteBuffer input;
320+
input.append(password.bytes());
321+
input.append(m_o_entry.bytes().slice(32, 8)); // See comment in compute_encryption_key_r6_and_later() re "Validation Salt".
322+
input.append(m_u_entry.bytes());
323+
auto hash = computing_a_hash_r6_and_later(input, password, HashKind::Owner);
324+
325+
return hash == m_o_entry.bytes().trim(32);
326+
}
327+
297328
bool StandardSecurityHandler::try_provide_user_password(StringView password_string)
298329
{
299330
bool has_user_password;

Userland/Libraries/LibPDF/Encryption.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class StandardSecurityHandler : public SecurityHandler {
5959

6060
bool authenticate_user_password_r2_to_r5(StringView password_string);
6161
bool authenticate_user_password_r6_and_later(StringView password_string);
62+
bool authenticate_owner_password_r6_and_later(StringView password_string);
6263

6364
ByteBuffer compute_encryption_key_r2_to_r5(ByteBuffer password_string);
6465
ByteBuffer compute_encryption_key_r6_and_later(ByteBuffer password_string);

0 commit comments

Comments
 (0)