📄 generalencryption.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 + -