Files
mmd-pdf/third_party/PdfSharpCore/Pdf.Security/EncryptorBase.cs
T

151 lines
5.4 KiB
C#

using PdfSharpCore.Pdf.Internal;
using System;
using System.Security.Cryptography;
namespace PdfSharpCore.Pdf.Security
{
internal abstract class EncryptorBase
{
protected readonly MD5 md5 = MD5.Create();
/// <summary>
/// The encryption key for the owner.
/// </summary>
protected byte[] ownerKey = new byte[32];
/// <summary>
/// The encryption key for the user.
/// </summary>
protected byte[] userKey = new byte[32];
/// <summary>
/// The encryption key for a particular object/generation.
/// </summary>
protected byte[] key;
/// <summary>
/// The global encryption key.
/// </summary>
protected byte[] encryptionKey;
/// <summary>
/// The /O value as read from the input document
/// </summary>
protected byte[] ownerValue;
/// <summary>
/// The /U value as read from the input document
/// </summary>
protected byte[] userValue;
protected byte[] computedOwnerValue;
protected byte[] computedUserValue;
protected byte[] documentId;
protected byte[] oeValue;
protected byte[] ueValue;
protected byte[] permsValue;
protected int pValue;
protected int rValue;
protected int vValue;
protected bool encryptMetadata;
protected PdfDictionary cf;
protected string stmF;
protected string strF;
protected int keyLength;
protected static readonly byte[] passwordPadding = new byte[] // 32 bytes password padding defined by Adobe
{
0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
};
/// <summary>
/// The encryption key length for a particular object/generation.
/// </summary>
protected int keySize;
protected PdfDocument doc;
protected PdfDictionary encryptionDict;
public bool PasswordValid { get; protected set; }
public bool HaveOwnerPermission { get; protected set; }
public void Initialize(PdfDocument document, PdfDictionary encryptionDictionary)
{
doc = document;
encryptionDict = encryptionDictionary;
documentId = PdfEncoders.RawEncoding.GetBytes(doc.Internals.FirstDocumentID);
ownerValue = PdfEncoders.RawEncoding.GetBytes(encryptionDict.Elements.GetString(PdfStandardSecurityHandler.Keys.O));
userValue = PdfEncoders.RawEncoding.GetBytes(encryptionDict.Elements.GetString(PdfStandardSecurityHandler.Keys.U));
oeValue = PdfEncoders.RawEncoding.GetBytes(encryptionDict.Elements.GetString(PdfStandardSecurityHandler.Keys.OE));
ueValue = PdfEncoders.RawEncoding.GetBytes(encryptionDict.Elements.GetString(PdfStandardSecurityHandler.Keys.UE));
permsValue = PdfEncoders.RawEncoding.GetBytes(encryptionDict.Elements.GetString(PdfStandardSecurityHandler.Keys.Perms));
pValue = encryptionDict.Elements.GetInteger(PdfStandardSecurityHandler.Keys.P);
rValue = encryptionDict.Elements.GetInteger(PdfStandardSecurityHandler.Keys.R);
vValue = encryptionDict.Elements.GetInteger(PdfSecurityHandler.Keys.V);
encryptMetadata = !encryptionDict.Elements.ContainsKey(PdfStandardSecurityHandler.Keys.EncryptMetadata) || encryptionDict.Elements.GetBoolean(PdfStandardSecurityHandler.Keys.EncryptMetadata);
cf = encryptionDict.Elements.GetDictionary(PdfSecurityHandler.Keys.CF);
stmF = encryptionDict.Elements.GetString(PdfSecurityHandler.Keys.StmF);
strF = encryptionDict.Elements.GetString(PdfSecurityHandler.Keys.StrF);
keyLength = encryptionDict.Elements.GetInteger(PdfSecurityHandler.Keys.Length) / 8; // specified in Bits
// Length may be absent, use default of 40 bits (see 7.6.1 Table 20, "V" entry)
if (keyLength <= 0)
keyLength = 5;
keySize = keyLength;
}
public void SetEncryptionKey(byte[] encKey)
{
encryptionKey = encKey;
}
/// <summary>
/// Pads a password to a 32 byte array.
/// </summary>
protected static byte[] PadPassword(string password)
{
var padded = new byte[32];
if (password == null)
Array.Copy(passwordPadding, 0, padded, 0, 32);
else
{
int length = password.Length;
Array.Copy(PdfEncoders.RawEncoding.GetBytes(password), 0, padded, 0, Math.Min(length, 32));
if (length < 32)
Array.Copy(passwordPadding, 0, padded, length, 32 - length);
}
return padded;
}
/// <summary>
/// Compares the first 'length' bytes of two byte-arrays
/// </summary>
/// <returns></returns>
protected static bool CompareArrays(byte[] left, byte[] right, int length)
{
for (var i = 0; i < length; i++)
{
if (left[i] != right[i])
return false;
}
return true;
}
}
}