using PdfSharpCore.Pdf.Internal; using System; using System.Security.Cryptography; namespace PdfSharpCore.Pdf.Security { internal abstract class EncryptorBase { protected readonly MD5 md5 = MD5.Create(); /// /// The encryption key for the owner. /// protected byte[] ownerKey = new byte[32]; /// /// The encryption key for the user. /// protected byte[] userKey = new byte[32]; /// /// The encryption key for a particular object/generation. /// protected byte[] key; /// /// The global encryption key. /// protected byte[] encryptionKey; /// /// The /O value as read from the input document /// protected byte[] ownerValue; /// /// The /U value as read from the input document /// 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, }; /// /// The encryption key length for a particular object/generation. /// 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; } /// /// Pads a password to a 32 byte array. /// 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; } /// /// Compares the first 'length' bytes of two byte-arrays /// /// 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; } } }