mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:27:36 +00:00
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
This commit is contained in:
parent
8f6c67a71c
commit
57768325cc
2 changed files with 32 additions and 0 deletions
|
@ -166,6 +166,19 @@ PDFErrorOr<NonnullRefPtr<StandardSecurityHandler>> StandardSecurityHandler::crea
|
||||||
if (encryption_dict->contains(CommonNames::EncryptMetadata))
|
if (encryption_dict->contains(CommonNames::EncryptMetadata))
|
||||||
encryption_dict->get_value(CommonNames::EncryptMetadata).get<bool>();
|
encryption_dict->get_value(CommonNames::EncryptMetadata).get<bool>();
|
||||||
|
|
||||||
|
if (v >= 5) {
|
||||||
|
// 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.
|
||||||
|
if (o.length() > 48)
|
||||||
|
o = o.substring(0, 48);
|
||||||
|
if (u.length() > 48)
|
||||||
|
u = u.substring(0, 48);
|
||||||
|
|
||||||
|
if (o.length() != 48)
|
||||||
|
return Error(Error::Type::Parse, "Invalid O size");
|
||||||
|
if (u.length() != 48)
|
||||||
|
return Error(Error::Type::Parse, "Invalid U size");
|
||||||
|
}
|
||||||
|
|
||||||
return adopt_ref(*new StandardSecurityHandler(document, revision, o, u, p, encrypt_metadata, length, method));
|
return adopt_ref(*new StandardSecurityHandler(document, revision, o, u, p, encrypt_metadata, length, method));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,6 +307,24 @@ bool StandardSecurityHandler::authenticate_user_password_r6_and_later(StringView
|
||||||
return hash == m_u_entry.bytes().trim(32);
|
return hash == m_u_entry.bytes().trim(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StandardSecurityHandler::authenticate_owner_password_r6_and_later(StringView password)
|
||||||
|
{
|
||||||
|
// ISO 32000 (PDF 2.0), 7.6.4.4.11 Algorithm 12: Authenticating the owner password (Security handlers of
|
||||||
|
// revision 6)
|
||||||
|
|
||||||
|
// a) Test the password against the owner key by computing the 32-byte hash using algorithm 2.B with an
|
||||||
|
// input string consisting of the UTF-8 password concatenated with the 8 bytes of Owner Validation Salt
|
||||||
|
// and the 48 byte U string. If the 32- byte result matches the first 32 bytes of the O string, this is the owner
|
||||||
|
// password.
|
||||||
|
ByteBuffer input;
|
||||||
|
input.append(password.bytes());
|
||||||
|
input.append(m_o_entry.bytes().slice(32, 8)); // See comment in compute_encryption_key_r6_and_later() re "Validation Salt".
|
||||||
|
input.append(m_u_entry.bytes());
|
||||||
|
auto hash = computing_a_hash_r6_and_later(input, password, HashKind::Owner);
|
||||||
|
|
||||||
|
return hash == m_o_entry.bytes().trim(32);
|
||||||
|
}
|
||||||
|
|
||||||
bool StandardSecurityHandler::try_provide_user_password(StringView password_string)
|
bool StandardSecurityHandler::try_provide_user_password(StringView password_string)
|
||||||
{
|
{
|
||||||
bool has_user_password;
|
bool has_user_password;
|
||||||
|
|
|
@ -59,6 +59,7 @@ private:
|
||||||
|
|
||||||
bool authenticate_user_password_r2_to_r5(StringView password_string);
|
bool authenticate_user_password_r2_to_r5(StringView password_string);
|
||||||
bool authenticate_user_password_r6_and_later(StringView password_string);
|
bool authenticate_user_password_r6_and_later(StringView password_string);
|
||||||
|
bool authenticate_owner_password_r6_and_later(StringView password_string);
|
||||||
|
|
||||||
ByteBuffer compute_encryption_key_r2_to_r5(ByteBuffer password_string);
|
ByteBuffer compute_encryption_key_r2_to_r5(ByteBuffer password_string);
|
||||||
ByteBuffer compute_encryption_key_r6_and_later(ByteBuffer password_string);
|
ByteBuffer compute_encryption_key_r6_and_later(ByteBuffer password_string);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue