begin adding support for in-document security handlers to support aes 128/256 encryption #34

This commit is contained in:
Eliot Jones
2019-06-08 14:14:51 +01:00
parent 39d05e6a47
commit a19122478d
8 changed files with 382 additions and 129 deletions

View 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);
}
}
}