mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-22 12:09:50 +08:00
106 lines
3.7 KiB
C#
106 lines
3.7 KiB
C#
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 if (cfmName == NameToken.Aesv3)
|
|
{
|
|
method = CryptDictionary.Method.AesV3;
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
}
|