mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-19 19:07:56 +08:00
finish revision 5 and 6 owner password handling #34
moves owner password check first. correctly calculates encryption key for owner password for revision 5 and 6.
This commit is contained in:
@@ -86,12 +86,7 @@
|
||||
: encryptionDictionary.KeyLength.GetValueOrDefault() / 8;
|
||||
|
||||
var isUserPassword = false;
|
||||
if (IsUserPassword(passwordBytes, encryptionDictionary, length, documentIdBytes))
|
||||
{
|
||||
decryptionPasswordBytes = passwordBytes;
|
||||
isUserPassword = true;
|
||||
}
|
||||
else if (IsOwnerPassword(passwordBytes, encryptionDictionary, length, documentIdBytes, out var userPassBytes))
|
||||
if (IsOwnerPassword(passwordBytes, encryptionDictionary, length, documentIdBytes, out var userPassBytes))
|
||||
{
|
||||
if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
|
||||
{
|
||||
@@ -102,6 +97,11 @@
|
||||
decryptionPasswordBytes = userPassBytes;
|
||||
}
|
||||
}
|
||||
else if (IsUserPassword(passwordBytes, encryptionDictionary, length, documentIdBytes))
|
||||
{
|
||||
decryptionPasswordBytes = passwordBytes;
|
||||
isUserPassword = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PdfDocumentEncryptedException("The document was encrypted and the provided password was neither the user or owner password.", encryptionDictionary);
|
||||
@@ -277,12 +277,15 @@
|
||||
Array.Copy(encryptionDictionary.OwnerBytes, ownerHash, ownerHash.Length);
|
||||
Array.Copy(encryptionDictionary.OwnerBytes, ownerHash.Length, validationSalt, 0, validationSalt.Length);
|
||||
|
||||
byte[] result;
|
||||
if (encryptionDictionary.Revision == 6)
|
||||
{
|
||||
throw new PdfDocumentEncryptedException($"Support for revision 6 encryption not implemented: {encryptionDictionary}.");
|
||||
result = ComputeStupidIsoHash(truncatedPassword, validationSalt, encryptionDictionary.UserBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ComputeSha256Hash(truncatedPassword, validationSalt, encryptionDictionary.UserBytes);
|
||||
}
|
||||
|
||||
var result = ComputeSha256Hash(truncatedPassword, validationSalt);
|
||||
|
||||
return result.SequenceEqual(ownerHash);
|
||||
}
|
||||
@@ -571,36 +574,53 @@
|
||||
// Truncate the UTF-8 representation of the password to 127 bytes if it is longer than 127 bytes
|
||||
password = TruncatePasswordTo127Bytes(password);
|
||||
|
||||
byte[] intermediateKey;
|
||||
byte[] encryptedFileKey;
|
||||
// If the password is the owner password:
|
||||
// Compute an intermediate owner key by computing the SHA-256 hash of the UTF-8 password concatenated with the 8 bytes of owner Key Salt,
|
||||
// concatenated with the 48-byte U string. The 32-byte result is the key used to decrypt the 32-byte OE string using AES-256 in CBC mode
|
||||
// with no padding and an initialization vector of zero. The 32-byte result is the file encryption key.
|
||||
if (!isUserPassword)
|
||||
{
|
||||
throw new PdfDocumentEncryptedException($"Unsupported owner key encryption with revision: {encryptionDictionary.Revision}.");
|
||||
}
|
||||
var ownerKeySalt = new byte[8];
|
||||
Array.Copy(encryptionDictionary.OwnerBytes, 40, ownerKeySalt, 0, ownerKeySalt.Length);
|
||||
|
||||
// If the password is the user password:
|
||||
// Compute an intermediate user key by computing the SHA-256 hash of the UTF-8 password concatenated with the 8 bytes of user Key Salt.
|
||||
// The 32-byte result is the key used to decrypt the 32-byte UE string using AES-256 in CBC mode with no padding and an initialization vector of zero.
|
||||
// The 32-byte result is the file encryption key.
|
||||
var userKeySalt = new byte[8];
|
||||
Array.Copy(encryptionDictionary.UserBytes, 40, userKeySalt, 0, 8);
|
||||
if (encryptionDictionary.Revision == 6)
|
||||
{
|
||||
intermediateKey = ComputeStupidIsoHash(password, ownerKeySalt, encryptionDictionary.UserBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
intermediateKey = ComputeSha256Hash(password, ownerKeySalt, encryptionDictionary.UserBytes);
|
||||
}
|
||||
|
||||
byte[] intermediateKey;
|
||||
if (encryptionDictionary.Revision == 6)
|
||||
{
|
||||
intermediateKey = ComputeStupidIsoHash(password, userKeySalt, null);
|
||||
encryptedFileKey = encryptionDictionary.OwnerEncryptionBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
intermediateKey = ComputeSha256Hash(password, userKeySalt);
|
||||
// If the password is the user password:
|
||||
// Compute an intermediate user key by computing the SHA-256 hash of the UTF-8 password concatenated with the 8 bytes of user Key Salt.
|
||||
// The 32-byte result is the key used to decrypt the 32-byte UE string using AES-256 in CBC mode with no padding and an initialization vector of zero.
|
||||
// The 32-byte result is the file encryption key.
|
||||
var userKeySalt = new byte[8];
|
||||
Array.Copy(encryptionDictionary.UserBytes, 40, userKeySalt, 0, 8);
|
||||
|
||||
if (encryptionDictionary.Revision == 6)
|
||||
{
|
||||
intermediateKey = ComputeStupidIsoHash(password, userKeySalt, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
intermediateKey = ComputeSha256Hash(password, userKeySalt);
|
||||
}
|
||||
|
||||
encryptedFileKey = encryptionDictionary.UserEncryptionBytes;
|
||||
}
|
||||
|
||||
|
||||
var iv = new byte[16];
|
||||
|
||||
using (var rijndaelManaged = new RijndaelManaged { Key = intermediateKey, IV = iv, Mode = CipherMode.CBC, Padding = PaddingMode.None })
|
||||
using (var memoryStream = new MemoryStream(encryptionDictionary.UserEncryptionBytes))
|
||||
using (var memoryStream = new MemoryStream(encryptedFileKey))
|
||||
using (var output = new MemoryStream())
|
||||
using (var cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateDecryptor(intermediateKey, iv), CryptoStreamMode.Read))
|
||||
{
|
||||
|
Reference in New Issue
Block a user