⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 generalencryption.cs

📁 PDF文件格式解析库源代码
💻 CS
字号:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using QiHe.CodeLib;

namespace AnotherPDFLib
{
    /// <summary>
    /// General Encryption Algorithm, also known as 
    /// Algorithm 3.1 Encryption of data using the RC4 or AES algorithms
    /// </summary>
    public partial class GeneralEncryption
    {
        public static void EncryptDocument(PdfDocument pdfdoc, PdfSecurityOptions securityOptions)
        {
            if (securityOptions.UserPassword == null)
            {
                securityOptions.UserPassword = "";
            }
            if (securityOptions.OwnerPassword == "")
            {
                securityOptions.OwnerPassword = null;
            }
            EncryptDocument(pdfdoc,
                securityOptions.UserPassword,
                securityOptions.OwnerPassword,
                (int)securityOptions.KeySize,
                (uint)securityOptions.GetUserAccessPermission());
        }

        private static byte[] PrepareKey(UInt32 objNum, UInt16 objGen, byte[] key)
        {
            int newlen = key.Length + 5;
            byte[] newKey = new byte[newlen];
            key.CopyTo(newKey, 0);
            BitConverter.GetBytes(objNum).CopyTo(newKey, key.Length);
            BitConverter.GetBytes(objGen).CopyTo(newKey, key.Length + 3);

            System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider();
            byte[] hash = md5.ComputeHash(newKey);
            if (newlen >= 16)
            {
                return hash;
            }
            else
            {
                Array.Copy(hash, newKey, newlen);
                return newKey;
            }
        }

        public static void EncryptDocument(PdfDocument pdfdoc, string userPwd, string ownerPwd, int keybits, uint permission)
        {
            if (pdfdoc.Trailer.Encrypt != null)
            {
                throw new Exception("The pdf document is already encrypted.");
            }
            if (keybits < 40 || keybits > 128 || keybits % 8 != 0)
            {
                throw new Exception("The length of the encryption key in bits must be a multiple of 8, in the range 40 to 128.");
            }
            int keyLength = keybits / 8;

            int revision = 3;
            byte[] fileID = pdfdoc.Trailer.FileID.OriginalID.Data;

            byte[] ownercheck = StandardSecurity.CreateOwnerCheck(userPwd, ownerPwd, keyLength, revision);

            byte[] key = StandardSecurity.CreateKey(
                userPwd,
                ownercheck,
                permission,
                fileID,
                true,
                revision,
                keyLength);

            byte[] usercheck = StandardSecurity.CreateUserCheck(key, fileID, revision);

            EncryptDocument(pdfdoc, key);

            PdfStandardEncryption stdEncrypt = new PdfStandardEncryption();
            stdEncrypt.Filter = "Standard";
            stdEncrypt.Version = 2;
            stdEncrypt.KeyLength = keybits;
            stdEncrypt.Revision = revision;
            stdEncrypt.Permissions = (int)permission;
            stdEncrypt["O"] = new PdfString(ownercheck);
            stdEncrypt["U"] = new PdfString(usercheck);

            pdfdoc.AddPdfObject(stdEncrypt);
            pdfdoc.Trailer.Encrypt = stdEncrypt;
        }

        private static void EncryptDocument(PdfDocument pdfdoc, byte[] key)
        {
            foreach (PdfObject pdfobj in pdfdoc.PdfObjects.Values)
            {
                byte[] pkey = PrepareKey(pdfobj.ID, pdfobj.Generation, key);
                EncryptObject(pdfobj, pkey);
            }
        }

        private static void EncryptObject(PdfObject pdfobj, byte[] pkey)
        {
            if (pdfobj is PdfString)
            {
                PdfString str = pdfobj as PdfString;
                byte[] bytes = RC4.EncryptDecrypt(str.Data, pkey);
                str.Data = bytes;
            }
            else if (pdfobj is PdfDictionary)
            {
                PdfDictionary dict = pdfobj as PdfDictionary;
                foreach (PdfObject subpdfobj in dict.Entries.Values)
                {
                    if (!subpdfobj.IsIndirect)
                    {
                        EncryptObject(subpdfobj, pkey);
                    }
                }

                if (pdfobj is PdfStream)
                {
                    PdfStream stream = pdfobj as PdfStream;
                    MemoryStream data = new MemoryStream((int)stream.Content.Length);
                    stream.Content.Position = 0;
                    RC4.EncryptDecrypt(stream.Content, data, pkey);
                    stream.Content = data;
                }
            }
            else if (pdfobj is PdfArray)
            {
                PdfArray array = pdfobj as PdfArray;
                foreach (PdfObject subpdfobj in array.Items)
                {
                    if (!subpdfobj.IsIndirect)
                    {
                        EncryptObject(subpdfobj, pkey);
                    }
                }
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -