mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-22 20:13:58 +08:00
begin adding support for in-document security handlers to support aes 128/256 encryption #34
This commit is contained in:
101
src/UglyToad.PdfPig/Encryption/CryptHandler.cs
Normal file
101
src/UglyToad.PdfPig/Encryption/CryptHandler.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
namespace UglyToad.PdfPig.Encryption
|
||||
{
|
||||
using System;
|
||||
using Exceptions;
|
||||
using Tokens;
|
||||
|
||||
internal class CryptHandler
|
||||
{
|
||||
private readonly DictionaryToken cryptDictionary;
|
||||
|
||||
public CryptDictionary StreamDictionary { get; }
|
||||
|
||||
public CryptDictionary StringDictionary { get; }
|
||||
|
||||
public CryptHandler(DictionaryToken cryptDictionary,
|
||||
NameToken streamName, NameToken stringName)
|
||||
{
|
||||
if (streamName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(streamName));
|
||||
}
|
||||
|
||||
if (stringName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stringName));
|
||||
}
|
||||
|
||||
this.cryptDictionary = cryptDictionary ?? throw new ArgumentNullException(nameof(cryptDictionary));
|
||||
StreamDictionary = ParseCryptDictionary(cryptDictionary, streamName);
|
||||
StringDictionary = ParseCryptDictionary(cryptDictionary, stringName);
|
||||
}
|
||||
|
||||
public CryptDictionary GetNamedCryptDictionary(NameToken name)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
return ParseCryptDictionary(cryptDictionary, name);
|
||||
}
|
||||
|
||||
private static CryptDictionary ParseCryptDictionary(DictionaryToken cryptDictionary, NameToken name)
|
||||
{
|
||||
if (name == NameToken.Identity)
|
||||
{
|
||||
return CryptDictionary.Identity;
|
||||
}
|
||||
|
||||
if (!cryptDictionary.TryGet(name, out DictionaryToken cryptDictionaryToken))
|
||||
{
|
||||
throw new PdfDocumentEncryptedException($"Could not find named crypt filter {name} for decryption in crypt dictionary: {cryptDictionaryToken}.");
|
||||
}
|
||||
|
||||
if (cryptDictionaryToken.TryGet(NameToken.Type, out NameToken typeName) && typeName != NameToken.CryptFilter)
|
||||
{
|
||||
throw new PdfDocumentEncryptedException($"Invalid crypt dictionary type {typeName} for crypt filter {name}: {cryptDictionaryToken}.");
|
||||
}
|
||||
|
||||
var cfmName = cryptDictionaryToken.TryGet(NameToken.Cfm, out NameToken cfm) ? cfm : NameToken.None;
|
||||
|
||||
CryptDictionary.Method method;
|
||||
if (cfmName == NameToken.None)
|
||||
{
|
||||
method = CryptDictionary.Method.None;
|
||||
}
|
||||
else if (cfmName == NameToken.V2)
|
||||
{
|
||||
method = CryptDictionary.Method.V2;
|
||||
}
|
||||
else if (cfmName == NameToken.Aesv2)
|
||||
{
|
||||
method = CryptDictionary.Method.AesV2;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PdfDocumentEncryptedException($"Unrecognized CFM option for crypt filter {cfm}: {cryptDictionaryToken}.");
|
||||
}
|
||||
|
||||
var eventName = cryptDictionaryToken.TryGet(NameToken.AuthEvent, out NameToken auth) ? auth : NameToken.DocOpen;
|
||||
|
||||
CryptDictionary.TriggerEvent @event;
|
||||
if (eventName == NameToken.DocOpen)
|
||||
{
|
||||
@event = CryptDictionary.TriggerEvent.DocumentOpen;
|
||||
}
|
||||
else if (eventName == NameToken.EfOpen)
|
||||
{
|
||||
@event = CryptDictionary.TriggerEvent.EmbeddedFileOpen;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PdfDocumentEncryptedException($"Unrecognized AuthEvent option for crypt filter {eventName}: {cryptDictionaryToken}.");
|
||||
}
|
||||
|
||||
var length = cryptDictionaryToken.TryGet(NameToken.Length, out NumericToken lengthNumeric) ? lengthNumeric.Int : 0;
|
||||
|
||||
return new CryptDictionary(method, @event, length);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user