finish initial support for rc4 encryption with blank user password

This commit is contained in:
Eliot Jones
2019-05-06 15:41:29 +01:00
parent 27928cd3a3
commit bad57763a1
15 changed files with 166 additions and 125 deletions

View File

@@ -3,17 +3,17 @@
//using System; //using System;
//using System.Diagnostics; //using System.Diagnostics;
//using System.IO; //using System.IO;
using Xunit; //using Xunit;
/// <summary> /// <summary>
/// A class for testing files which are not checked in to source control. /// A class for testing files which are not checked in to source control.
/// </summary> /// </summary>
public class LocalTests public class LocalTests
{ {
[Fact] //[Fact]
public void Tests() //public void Tests()
{ //{
// var files = new[]{ @"C:\Users\eliot\Downloads\Encrypted1.pdf" }; // var files = new[] { @"C:\Users\eliot\Downloads\Encrypted1.pdf" };
// foreach (var file in files) // foreach (var file in files)
// { // {
@@ -34,6 +34,6 @@
// throw new InvalidOperationException($"Error parsing: {Path.GetFileName(file)}.", ex); // throw new InvalidOperationException($"Error parsing: {Path.GetFileName(file)}.", ex);
// } // }
// } // }
} //}
} }
} }

View File

@@ -4,7 +4,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content; using Content;
using Encryption;
using Exceptions; using Exceptions;
using Fields; using Fields;
using Filters; using Filters;
@@ -21,13 +20,11 @@
{ {
private readonly IPdfTokenScanner tokenScanner; private readonly IPdfTokenScanner tokenScanner;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IEncryptionHandler encryptionHandler;
public AcroFormFactory(IPdfTokenScanner tokenScanner, IFilterProvider filterProvider, IEncryptionHandler encryptionHandler) public AcroFormFactory(IPdfTokenScanner tokenScanner, IFilterProvider filterProvider)
{ {
this.tokenScanner = tokenScanner ?? throw new ArgumentNullException(nameof(tokenScanner)); this.tokenScanner = tokenScanner ?? throw new ArgumentNullException(nameof(tokenScanner));
this.filterProvider = filterProvider ?? throw new ArgumentNullException(nameof(filterProvider)); this.filterProvider = filterProvider ?? throw new ArgumentNullException(nameof(filterProvider));
this.encryptionHandler = encryptionHandler ?? throw new ArgumentNullException(nameof(encryptionHandler));
} }
/// <summary> /// <summary>
@@ -215,7 +212,7 @@
} }
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StreamToken valueStreamToken)) else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StreamToken valueStreamToken))
{ {
textValue = OtherEncodings.BytesAsLatin1String(valueStreamToken.Decode(filterProvider, encryptionHandler).ToArray()); textValue = OtherEncodings.BytesAsLatin1String(valueStreamToken.Decode(filterProvider).ToArray());
} }
} }

View File

@@ -2,6 +2,7 @@
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using CrossReference; using CrossReference;
@@ -23,6 +24,8 @@
0x64, 0x53, 0x69, 0x7A 0x64, 0x53, 0x69, 0x7A
}; };
private readonly HashSet<IndirectReference> previouslyDecrypted = new HashSet<IndirectReference>();
[CanBeNull] [CanBeNull]
private readonly EncryptionDictionary encryptionDictionary; private readonly EncryptionDictionary encryptionDictionary;
@@ -67,43 +70,110 @@
? 5 ? 5
: encryptionDictionary.KeyLength.GetValueOrDefault() / 8; : encryptionDictionary.KeyLength.GetValueOrDefault() / 8;
encryptionKey = CalculateKeyRevisions2To4(passwordBytes, ownerKey, (int) encryptionDictionary.UserAccessPermissions, encryptionDictionary.StandardSecurityHandlerRevision, encryptionKey = CalculateKeyRevisions2To4(passwordBytes, ownerKey, (int)encryptionDictionary.UserAccessPermissions, encryptionDictionary.StandardSecurityHandlerRevision,
length, documentIdBytes, encryptionDictionary.EncryptMetadata); length, documentIdBytes, encryptionDictionary.EncryptMetadata);
useAes = false;
} }
public IReadOnlyList<byte> Decrypt(StreamToken stream) public IToken Decrypt(IndirectReference reference, IToken token)
{ {
if (encryptionDictionary == null) if (token == null)
{ {
return stream?.Data; throw new ArgumentNullException(nameof(token));
} }
if (stream == null) token = DecryptInternal(reference, token);
{
throw new ArgumentNullException(nameof(stream)); previouslyDecrypted.Add(reference);
return token;
} }
throw new NotImplementedException($"Encryption is not supported yet. Encryption used in document was: {encryptionDictionary.Dictionary}."); private IToken DecryptInternal(IndirectReference reference, IToken token)
{
switch (token)
{
case StreamToken stream:
{
if (stream.StreamDictionary.TryGet(NameToken.Type, out NameToken typeName))
{
if (NameToken.Xref.Equals(typeName))
{
return token;
} }
public void Decrypt(IndirectReference reference, IToken token) if (!encryptionDictionary.EncryptMetadata && NameToken.Metadata.Equals(typeName))
{ {
if (token is StreamToken stream) return token;
{
} }
else if (token is StringToken stringToken)
{
// TODO: check unencrypted metadata
} }
else if (token is DictionaryToken dictionary)
{
} var streamDictionary = (DictionaryToken)DecryptInternal(reference, stream.StreamDictionary);
else if (token is ArrayToken array)
{
var decrypted = DecryptData(stream.Data.ToArray(), reference);
token = new StreamToken(streamDictionary, decrypted);
break;
} }
case StringToken stringToken:
{
var data = OtherEncodings.StringAsLatin1Bytes(stringToken.Data);
var decrypted = DecryptData(data, reference);
token = new StringToken(OtherEncodings.BytesAsLatin1String(decrypted));
break;
}
case DictionaryToken dictionary:
{
// PDFBOX-2936: avoid orphan /CF dictionaries found in US govt "I-" files
if (dictionary.TryGet(NameToken.Cf, out _))
{
return token;
}
var isSignatureDictionary = dictionary.TryGet(NameToken.Type, out NameToken typeName)
&& (typeName.Equals(NameToken.Sig) || typeName.Equals(NameToken.DocTimeStamp));
foreach (var keyValuePair in dictionary.Data)
{
if (isSignatureDictionary && keyValuePair.Key == NameToken.Contents.Data)
{
continue;
}
if (keyValuePair.Value is StringToken || keyValuePair.Value is ArrayToken || keyValuePair.Value is DictionaryToken)
{
var inner = DecryptInternal(reference, keyValuePair.Value);
dictionary = dictionary.With(keyValuePair.Key, inner);
}
}
token = dictionary;
break;
}
case ArrayToken array:
{
var result = new IToken[array.Length];
for (var i = 0; i < array.Length; i++)
{
result[i] = DecryptInternal(reference, array.Data[i]);
}
token = new ArrayToken(result);
break;
}
}
return token;
} }
private byte[] DecryptData(byte[] data, IndirectReference reference) private byte[] DecryptData(byte[] data, IndirectReference reference)
@@ -134,12 +204,12 @@
var finalKey = new byte[encryptionKey.Length + 5 + (useAes ? 4 : 0)]; var finalKey = new byte[encryptionKey.Length + 5 + (useAes ? 4 : 0)];
Array.Copy(encryptionKey, finalKey, encryptionKey.Length); Array.Copy(encryptionKey, finalKey, encryptionKey.Length);
finalKey[encryptionKey.Length] = (byte) reference.ObjectNumber; finalKey[encryptionKey.Length] = (byte)reference.ObjectNumber;
finalKey[encryptionKey.Length + 1] = (byte) (reference.ObjectNumber >> 1); finalKey[encryptionKey.Length + 1] = (byte)(reference.ObjectNumber >> 8);
finalKey[encryptionKey.Length + 2] = (byte) (reference.ObjectNumber >> 2); finalKey[encryptionKey.Length + 2] = (byte)(reference.ObjectNumber >> 16);
finalKey[encryptionKey.Length + 3] = (byte) reference.Generation; finalKey[encryptionKey.Length + 3] = (byte)reference.Generation;
finalKey[encryptionKey.Length + 4] = (byte) (reference.Generation >> 1); finalKey[encryptionKey.Length + 4] = (byte)(reference.Generation >> 8);
// 2. If using the AES algorithm extend the encryption key by 4 bytes by adding the value "sAlT". // 2. If using the AES algorithm extend the encryption key by 4 bytes by adding the value "sAlT".
if (useAes) if (useAes)
@@ -195,32 +265,28 @@
using (var md5 = MD5.Create()) using (var md5 = MD5.Create())
{ {
// 2. Initialize the MD5 hash function and pass the result of step 1 as input to this function. // 2. Initialize the MD5 hash function and pass the result of step 1 as input to this function.
var has = md5.ComputeHash(passwordFull); UpdateMd5(md5, passwordFull);
// 3. Pass the value of the encryption dictionary's owner key entry to the MD5 hash function. // 3. Pass the value of the encryption dictionary's owner key entry to the MD5 hash function.
var has1 = md5.ComputeHash(ownerKey); UpdateMd5(md5, ownerKey);
// 4. Treat the value of the P entry as an unsigned 4-byte integer. // 4. Treat the value of the P entry as an unsigned 4-byte integer.
var unsigned = (uint) permissions; var unsigned = (uint)permissions;
var permissionsBytes = new []
{
(byte) (unsigned),
(byte) (unsigned >> 8),
(byte) (unsigned >> 16),
(byte) (unsigned >> 24)
};
// 4. Pass these bytes to the MD5 hash function, low-order byte first. // 4. Pass these bytes to the MD5 hash function, low-order byte first.
var has2 = md5.ComputeHash(permissionsBytes); UpdateMd5(md5, new[] { (byte)(unsigned) });
UpdateMd5(md5, new[] { (byte)(unsigned >> 8) });
UpdateMd5(md5, new[] { (byte)(unsigned >> 16) });
UpdateMd5(md5, new[] { (byte)(unsigned >> 24) });
// 5. Pass the first element of the file's file identifier array to the hash. // 5. Pass the first element of the file's file identifier array to the hash.
var has3 = md5.ComputeHash(documentId); UpdateMd5(md5, documentId);
// 6. (Revision 4 or greater) If document metadata is not being encrypted, pass 4 bytes // 6. (Revision 4 or greater) If document metadata is not being encrypted, pass 4 bytes
// with the value 0xFFFFFFFF to the MD5 hash function. // with the value 0xFFFFFFFF to the MD5 hash function.
if (revision >= 4) if (revision >= 4)
{ {
md5.ComputeHash(new byte[] {0xFF, 0xFF, 0xFF, 0xFF}); UpdateMd5(md5, new byte[] { 0xFF, 0xFF, 0xFF, 0xFF });
} }
// 7. Do the following 50 times: Take the output from the previous MD5 hash and // 7. Do the following 50 times: Take the output from the previous MD5 hash and
@@ -235,11 +301,13 @@
for (var i = 0; i < 50; i++) for (var i = 0; i < 50; i++)
{ {
md5.ComputeHash(input, 0, n); UpdateMd5(md5, input.Take(n).ToArray());
input = md5.Hash; input = md5.Hash;
} }
} }
md5.TransformFinalBlock(EmptyArray<byte>.Instance, 0, 0);
var result = new byte[length]; var result = new byte[length];
Array.Copy(md5.Hash, result, length); Array.Copy(md5.Hash, result, length);
@@ -248,6 +316,11 @@
} }
} }
private static void UpdateMd5(MD5 md5, byte[] data)
{
md5.TransformBlock(data, 0, data.Length, null, 0);
}
private static byte[] GetPaddedPassword(byte[] password) private static byte[] GetPaddedPassword(byte[] password)
{ {
if (password == null || password.Length == 0) if (password == null || password.Length == 0)

View File

@@ -1,6 +1,5 @@
namespace UglyToad.PdfPig.Encryption namespace UglyToad.PdfPig.Encryption
{ {
using System.Collections.Generic;
using Tokens; using Tokens;
/// <summary> /// <summary>
@@ -8,9 +7,6 @@
/// </summary> /// </summary>
internal interface IEncryptionHandler internal interface IEncryptionHandler
{ {
/// <summary> IToken Decrypt(IndirectReference reference, IToken token);
/// Decrypt the contents of the stream if encryption is applied.
/// </summary>
IReadOnlyList<byte> Decrypt(StreamToken stream);
} }
} }

View File

@@ -1,6 +1,5 @@
namespace UglyToad.PdfPig.Encryption namespace UglyToad.PdfPig.Encryption
{ {
using System.Collections.Generic;
using Tokens; using Tokens;
internal class NoOpEncryptionHandler : IEncryptionHandler internal class NoOpEncryptionHandler : IEncryptionHandler
@@ -11,9 +10,9 @@
{ {
} }
public IReadOnlyList<byte> Decrypt(StreamToken stream) public IToken Decrypt(IndirectReference reference, IToken token)
{ {
return stream.Data; return token;
} }
} }
} }

View File

@@ -4,7 +4,6 @@
using SystemFonts; using SystemFonts;
using Cmap; using Cmap;
using Encodings; using Encodings;
using Encryption;
using Exceptions; using Exceptions;
using Filters; using Filters;
using IO; using IO;
@@ -23,7 +22,6 @@
private readonly ILog log; private readonly ILog log;
private readonly IPdfTokenScanner pdfScanner; private readonly IPdfTokenScanner pdfScanner;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IEncryptionHandler encryptionHandler;
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly FontDescriptorFactory fontDescriptorFactory; private readonly FontDescriptorFactory fontDescriptorFactory;
private readonly TrueTypeFontParser trueTypeFontParser; private readonly TrueTypeFontParser trueTypeFontParser;
@@ -31,7 +29,6 @@
private readonly ISystemFontFinder systemFontFinder; private readonly ISystemFontFinder systemFontFinder;
public TrueTypeFontHandler(ILog log, IPdfTokenScanner pdfScanner, IFilterProvider filterProvider, public TrueTypeFontHandler(ILog log, IPdfTokenScanner pdfScanner, IFilterProvider filterProvider,
IEncryptionHandler encryptionHandler,
CMapCache cMapCache, CMapCache cMapCache,
FontDescriptorFactory fontDescriptorFactory, FontDescriptorFactory fontDescriptorFactory,
TrueTypeFontParser trueTypeFontParser, TrueTypeFontParser trueTypeFontParser,
@@ -40,7 +37,6 @@
{ {
this.log = log; this.log = log;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.encryptionHandler = encryptionHandler;
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.fontDescriptorFactory = fontDescriptorFactory; this.fontDescriptorFactory = fontDescriptorFactory;
this.trueTypeFontParser = trueTypeFontParser; this.trueTypeFontParser = trueTypeFontParser;
@@ -89,7 +85,7 @@
{ {
var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, pdfScanner); var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, pdfScanner);
var decodedUnicodeCMap = toUnicode.Decode(filterProvider, encryptionHandler); var decodedUnicodeCMap = toUnicode.Decode(filterProvider);
if (decodedUnicodeCMap != null) if (decodedUnicodeCMap != null)
{ {
@@ -129,7 +125,7 @@
var fontFileStream = DirectObjectFinder.Get<StreamToken>(descriptor.FontFile.ObjectKey, pdfScanner); var fontFileStream = DirectObjectFinder.Get<StreamToken>(descriptor.FontFile.ObjectKey, pdfScanner);
var fontFile = fontFileStream.Decode(filterProvider, encryptionHandler); var fontFile = fontFileStream.Decode(filterProvider);
var font = trueTypeFontParser.Parse(new TrueTypeDataBytes(new ByteArrayInputBytes(fontFile))); var font = trueTypeFontParser.Parse(new TrueTypeDataBytes(new ByteArrayInputBytes(fontFile)));

View File

@@ -4,7 +4,6 @@
using CidFonts; using CidFonts;
using Cmap; using Cmap;
using Composite; using Composite;
using Encryption;
using Exceptions; using Exceptions;
using Filters; using Filters;
using IO; using IO;
@@ -19,17 +18,14 @@
private readonly CidFontFactory cidFontFactory; private readonly CidFontFactory cidFontFactory;
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IEncryptionHandler encryptionHandler;
private readonly IPdfTokenScanner scanner; private readonly IPdfTokenScanner scanner;
public Type0FontHandler(CidFontFactory cidFontFactory, CMapCache cMapCache, IFilterProvider filterProvider, public Type0FontHandler(CidFontFactory cidFontFactory, CMapCache cMapCache, IFilterProvider filterProvider,
IEncryptionHandler encryptionHandler,
IPdfTokenScanner scanner) IPdfTokenScanner scanner)
{ {
this.cidFontFactory = cidFontFactory; this.cidFontFactory = cidFontFactory;
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.encryptionHandler = encryptionHandler;
this.scanner = scanner; this.scanner = scanner;
} }
@@ -72,7 +68,7 @@
var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeValue, scanner); var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeValue, scanner);
var decodedUnicodeCMap = toUnicode?.Decode(filterProvider, encryptionHandler); var decodedUnicodeCMap = toUnicode?.Decode(filterProvider);
if (decodedUnicodeCMap != null) if (decodedUnicodeCMap != null)
{ {
@@ -151,7 +147,7 @@
} }
else if (value is StreamToken stream) else if (value is StreamToken stream)
{ {
var decoded = stream.Decode(filterProvider, encryptionHandler); var decoded = stream.Decode(filterProvider);
var cmap = cMapCache.Parse(new ByteArrayInputBytes(decoded), false); var cmap = cMapCache.Parse(new ByteArrayInputBytes(decoded), false);

View File

@@ -1,10 +1,8 @@
namespace UglyToad.PdfPig.Fonts.Parser.Handlers namespace UglyToad.PdfPig.Fonts.Parser.Handlers
{ {
using System.Linq;
using Cmap; using Cmap;
using CompactFontFormat; using CompactFontFormat;
using Encodings; using Encodings;
using Encryption;
using Exceptions; using Exceptions;
using Filters; using Filters;
using IO; using IO;
@@ -22,14 +20,12 @@
private readonly IPdfTokenScanner pdfScanner; private readonly IPdfTokenScanner pdfScanner;
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IEncryptionHandler encryptionHandler;
private readonly FontDescriptorFactory fontDescriptorFactory; private readonly FontDescriptorFactory fontDescriptorFactory;
private readonly IEncodingReader encodingReader; private readonly IEncodingReader encodingReader;
private readonly Type1FontParser type1FontParser; private readonly Type1FontParser type1FontParser;
private readonly CompactFontFormatParser compactFontFormatParser; private readonly CompactFontFormatParser compactFontFormatParser;
public Type1FontHandler(IPdfTokenScanner pdfScanner, CMapCache cMapCache, IFilterProvider filterProvider, public Type1FontHandler(IPdfTokenScanner pdfScanner, CMapCache cMapCache, IFilterProvider filterProvider,
IEncryptionHandler encryptionHandler,
FontDescriptorFactory fontDescriptorFactory, FontDescriptorFactory fontDescriptorFactory,
IEncodingReader encodingReader, IEncodingReader encodingReader,
Type1FontParser type1FontParser, Type1FontParser type1FontParser,
@@ -38,7 +34,6 @@
this.pdfScanner = pdfScanner; this.pdfScanner = pdfScanner;
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.encryptionHandler = encryptionHandler;
this.fontDescriptorFactory = fontDescriptorFactory; this.fontDescriptorFactory = fontDescriptorFactory;
this.encodingReader = encodingReader; this.encodingReader = encodingReader;
this.type1FontParser = type1FontParser; this.type1FontParser = type1FontParser;
@@ -93,7 +88,7 @@
{ {
var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, pdfScanner); var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, pdfScanner);
var decodedUnicodeCMap = toUnicode?.Decode(filterProvider, encryptionHandler); var decodedUnicodeCMap = toUnicode?.Decode(filterProvider);
if (decodedUnicodeCMap != null) if (decodedUnicodeCMap != null)
{ {
@@ -130,7 +125,7 @@
return null; return null;
} }
var bytes = stream.Decode(filterProvider, encryptionHandler); var bytes = stream.Decode(filterProvider);
// We have a Compact Font Format font rather than an Adobe Type 1 Font. // We have a Compact Font Format font rather than an Adobe Type 1 Font.
if (stream.StreamDictionary.TryGet(NameToken.Subtype, out NameToken subTypeName) if (stream.StreamDictionary.TryGet(NameToken.Subtype, out NameToken subTypeName)

View File

@@ -3,7 +3,6 @@
using Cmap; using Cmap;
using Core; using Core;
using Encodings; using Encodings;
using Encryption;
using Exceptions; using Exceptions;
using Filters; using Filters;
using Geometry; using Geometry;
@@ -18,17 +17,14 @@
{ {
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IEncryptionHandler encryptionHandler;
private readonly IEncodingReader encodingReader; private readonly IEncodingReader encodingReader;
private readonly IPdfTokenScanner scanner; private readonly IPdfTokenScanner scanner;
public Type3FontHandler(IPdfTokenScanner scanner, CMapCache cMapCache, IFilterProvider filterProvider, public Type3FontHandler(IPdfTokenScanner scanner, CMapCache cMapCache, IFilterProvider filterProvider,
IEncryptionHandler encryptionHandler,
IEncodingReader encodingReader) IEncodingReader encodingReader)
{ {
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.encryptionHandler = encryptionHandler;
this.encodingReader = encodingReader; this.encodingReader = encodingReader;
this.scanner = scanner; this.scanner = scanner;
} }
@@ -50,7 +46,7 @@
{ {
var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, scanner); var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, scanner);
var decodedUnicodeCMap = toUnicode?.Decode(filterProvider, encryptionHandler); var decodedUnicodeCMap = toUnicode?.Decode(filterProvider);
if (decodedUnicodeCMap != null) if (decodedUnicodeCMap != null)
{ {

View File

@@ -4,7 +4,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using CidFonts; using CidFonts;
using CompactFontFormat; using CompactFontFormat;
using Encryption;
using Exceptions; using Exceptions;
using Filters; using Filters;
using Geometry; using Geometry;
@@ -23,21 +22,18 @@
private readonly TrueTypeFontParser trueTypeFontParser; private readonly TrueTypeFontParser trueTypeFontParser;
private readonly CompactFontFormatParser compactFontFormatParser; private readonly CompactFontFormatParser compactFontFormatParser;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IEncryptionHandler encryptionHandler;
private readonly IPdfTokenScanner pdfScanner; private readonly IPdfTokenScanner pdfScanner;
public CidFontFactory(IPdfTokenScanner pdfScanner, FontDescriptorFactory descriptorFactory, public CidFontFactory(IPdfTokenScanner pdfScanner, FontDescriptorFactory descriptorFactory,
TrueTypeFontParser trueTypeFontParser, TrueTypeFontParser trueTypeFontParser,
CompactFontFormatParser compactFontFormatParser, CompactFontFormatParser compactFontFormatParser,
IFilterProvider filterProvider, IFilterProvider filterProvider)
IEncryptionHandler encryptionHandler)
{ {
this.pdfScanner = pdfScanner; this.pdfScanner = pdfScanner;
this.descriptorFactory = descriptorFactory; this.descriptorFactory = descriptorFactory;
this.trueTypeFontParser = trueTypeFontParser; this.trueTypeFontParser = trueTypeFontParser;
this.compactFontFormatParser = compactFontFormatParser; this.compactFontFormatParser = compactFontFormatParser;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.encryptionHandler = encryptionHandler;
} }
public ICidFont Generate(DictionaryToken dictionary, bool isLenientParsing) public ICidFont Generate(DictionaryToken dictionary, bool isLenientParsing)
@@ -109,7 +105,7 @@
return null; return null;
} }
var fontFile = fontFileStream.Decode(filterProvider, encryptionHandler); var fontFile = fontFileStream.Decode(filterProvider);
switch (descriptor.FontFile.FileType) switch (descriptor.FontFile.FileType)
{ {
@@ -130,7 +126,7 @@
if (subtypeName == NameToken.CidFontType0C) if (subtypeName == NameToken.CidFontType0C)
{ {
var bytes = str.Decode(filterProvider, encryptionHandler); var bytes = str.Decode(filterProvider);
var font = compactFontFormatParser.Parse(new CompactFontFormatData(bytes)); var font = compactFontFormatParser.Parse(new CompactFontFormatData(bytes));
return font; return font;
} }
@@ -302,7 +298,7 @@
var stream = DirectObjectFinder.Get<StreamToken>(entry, pdfScanner); var stream = DirectObjectFinder.Get<StreamToken>(entry, pdfScanner);
var bytes = stream.Decode(filterProvider, encryptionHandler); var bytes = stream.Decode(filterProvider);
return new CharacterIdentifierToGlyphIndexMap(bytes); return new CharacterIdentifierToGlyphIndexMap(bytes);
} }

View File

@@ -22,20 +22,17 @@
private readonly IPdfTokenScanner pdfScanner; private readonly IPdfTokenScanner pdfScanner;
private readonly IResourceStore resourceStore; private readonly IResourceStore resourceStore;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IEncryptionHandler encryptionHandler;
private readonly IPageContentParser pageContentParser; private readonly IPageContentParser pageContentParser;
private readonly XObjectFactory xObjectFactory; private readonly XObjectFactory xObjectFactory;
private readonly ILog log; private readonly ILog log;
public PageFactory(IPdfTokenScanner pdfScanner, IResourceStore resourceStore, IFilterProvider filterProvider, public PageFactory(IPdfTokenScanner pdfScanner, IResourceStore resourceStore, IFilterProvider filterProvider,
IEncryptionHandler encryptionHandler,
IPageContentParser pageContentParser, IPageContentParser pageContentParser,
XObjectFactory xObjectFactory, XObjectFactory xObjectFactory,
ILog log) ILog log)
{ {
this.resourceStore = resourceStore; this.resourceStore = resourceStore;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.encryptionHandler = encryptionHandler;
this.pageContentParser = pageContentParser; this.pageContentParser = pageContentParser;
this.xObjectFactory = xObjectFactory; this.xObjectFactory = xObjectFactory;
this.log = log; this.log = log;
@@ -88,7 +85,7 @@
throw new InvalidOperationException($"Could not find the contents for object {obj}."); throw new InvalidOperationException($"Could not find the contents for object {obj}.");
} }
bytes.AddRange(contentStream.Decode(filterProvider, encryptionHandler)); bytes.AddRange(contentStream.Decode(filterProvider));
} }
content = GetContent(bytes, cropBox, userSpaceUnit, isLenientParsing); content = GetContent(bytes, cropBox, userSpaceUnit, isLenientParsing);
@@ -102,7 +99,7 @@
throw new InvalidOperationException("Failed to parse the content for the page: " + number); throw new InvalidOperationException("Failed to parse the content for the page: " + number);
} }
var bytes = contentStream.Decode(filterProvider, encryptionHandler); var bytes = contentStream.Decode(filterProvider);
content = GetContent(bytes, cropBox, userSpaceUnit, isLenientParsing); content = GetContent(bytes, cropBox, userSpaceUnit, isLenientParsing);
} }

View File

@@ -1,7 +1,6 @@
namespace UglyToad.PdfPig.Parser.Parts.CrossReference namespace UglyToad.PdfPig.Parser.Parts.CrossReference
{ {
using System.Collections.Generic; using System.Collections.Generic;
using Encryption;
using Exceptions; using Exceptions;
using Filters; using Filters;
using PdfPig.CrossReference; using PdfPig.CrossReference;
@@ -22,7 +21,7 @@
/// </summary> /// </summary>
public CrossReferenceTablePart Parse(long streamOffset, StreamToken stream) public CrossReferenceTablePart Parse(long streamOffset, StreamToken stream)
{ {
var decoded = stream.Decode(filterProvider, NoOpEncryptionHandler.Instance); var decoded = stream.Decode(filterProvider);
var fieldSizes = new CrossReferenceStreamFieldSize(stream.StreamDictionary); var fieldSizes = new CrossReferenceStreamFieldSize(stream.StreamDictionary);

View File

@@ -107,25 +107,25 @@
var rootDictionary = ParseTrailer(crossReferenceTable, isLenientParsing, pdfScanner, out var encryptionDictionary); var rootDictionary = ParseTrailer(crossReferenceTable, isLenientParsing, pdfScanner, out var encryptionDictionary);
var encryptionHandler = new EncryptionHandler(encryptionDictionary, crossReferenceTable.Trailer, string.Empty); var encryptionHandler = encryptionDictionary != null ? (IEncryptionHandler)new EncryptionHandler(encryptionDictionary, crossReferenceTable.Trailer, string.Empty)
: NoOpEncryptionHandler.Instance;
pdfScanner.UpdateEncryptionHandler(encryptionHandler); pdfScanner.UpdateEncryptionHandler(encryptionHandler);
var cidFontFactory = new CidFontFactory(pdfScanner, fontDescriptorFactory, trueTypeFontParser, compactFontFormatParser, filterProvider, encryptionHandler); var cidFontFactory = new CidFontFactory(pdfScanner, fontDescriptorFactory, trueTypeFontParser, compactFontFormatParser, filterProvider);
var encodingReader = new EncodingReader(pdfScanner); var encodingReader = new EncodingReader(pdfScanner);
var fontFactory = new FontFactory(log, new Type0FontHandler(cidFontFactory, var fontFactory = new FontFactory(log, new Type0FontHandler(cidFontFactory,
cMapCache, cMapCache,
filterProvider, encryptionHandler, pdfScanner), filterProvider, pdfScanner),
new TrueTypeFontHandler(log, pdfScanner, filterProvider, encryptionHandler, cMapCache, fontDescriptorFactory, trueTypeFontParser, encodingReader, new SystemFontFinder(new TrueTypeFontParser())), new TrueTypeFontHandler(log, pdfScanner, filterProvider, cMapCache, fontDescriptorFactory, trueTypeFontParser, encodingReader, new SystemFontFinder(new TrueTypeFontParser())),
new Type1FontHandler(pdfScanner, cMapCache, filterProvider, encryptionHandler, fontDescriptorFactory, encodingReader, new Type1FontHandler(pdfScanner, cMapCache, filterProvider, fontDescriptorFactory, encodingReader,
new Type1FontParser(new Type1EncryptedPortionParser()), compactFontFormatParser), new Type1FontParser(new Type1EncryptedPortionParser()), compactFontFormatParser),
new Type3FontHandler(pdfScanner, cMapCache, filterProvider, encryptionHandler, encodingReader)); new Type3FontHandler(pdfScanner, cMapCache, filterProvider, encodingReader));
var resourceContainer = new ResourceContainer(pdfScanner, fontFactory); var resourceContainer = new ResourceContainer(pdfScanner, fontFactory);
var pageFactory = new PageFactory(pdfScanner, resourceContainer, filterProvider, var pageFactory = new PageFactory(pdfScanner, resourceContainer, filterProvider,
encryptionHandler,
new PageContentParser(new ReflectionGraphicsStateOperationFactory()), new PageContentParser(new ReflectionGraphicsStateOperationFactory()),
new XObjectFactory(), log); new XObjectFactory(), log);
var informationFactory = new DocumentInformationFactory(); var informationFactory = new DocumentInformationFactory();
@@ -136,7 +136,7 @@
var caching = new ParsingCachingProviders(bruteForceSearcher, resourceContainer); var caching = new ParsingCachingProviders(bruteForceSearcher, resourceContainer);
var acroFormFactory = new AcroFormFactory(pdfScanner, filterProvider, encryptionHandler); var acroFormFactory = new AcroFormFactory(pdfScanner, filterProvider);
return new PdfDocument(log, inputBytes, version, crossReferenceTable, isLenientParsing, caching, pageFactory, catalog, information, return new PdfDocument(log, inputBytes, version, crossReferenceTable, isLenientParsing, caching, pageFactory, catalog, information,
encryptionDictionary, encryptionDictionary,

View File

@@ -158,6 +158,8 @@
token = readTokens[readTokens.Count - 1]; token = readTokens[readTokens.Count - 1];
} }
token = encryptionHandler.Decrypt(reference, token);
CurrentToken = new ObjectToken(startPosition, reference, token); CurrentToken = new ObjectToken(startPosition, reference, token);
objectLocationProvider.UpdateOffset(reference, startPosition); objectLocationProvider.UpdateOffset(reference, startPosition);
@@ -537,7 +539,7 @@
} }
// Read the N integers // Read the N integers
var bytes = new ByteArrayInputBytes(stream.Decode(filterProvider, encryptionHandler)); var bytes = new ByteArrayInputBytes(stream.Decode(filterProvider));
var scanner = new CoreTokenScanner(bytes); var scanner = new CoreTokenScanner(bytes);

View File

@@ -2,7 +2,6 @@
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Encryption;
using Filters; using Filters;
using Util.JetBrains.Annotations; using Util.JetBrains.Annotations;
@@ -39,7 +38,7 @@
Data = data ?? throw new ArgumentNullException(nameof(data)); Data = data ?? throw new ArgumentNullException(nameof(data));
} }
internal IReadOnlyList<byte> Decode(IFilterProvider filterProvider, IEncryptionHandler encryptionHandler) internal IReadOnlyList<byte> Decode(IFilterProvider filterProvider)
{ {
lock (lockObject) lock (lockObject)
{ {
@@ -50,7 +49,7 @@
var filters = filterProvider.GetFilters(StreamDictionary); var filters = filterProvider.GetFilters(StreamDictionary);
var transform = encryptionHandler.Decrypt(this); var transform = Data;
for (var i = 0; i < filters.Count; i++) for (var i = 0; i < filters.Count; i++)
{ {
transform = filters[i].Decode(transform, StreamDictionary, i); transform = filters[i].Decode(transform, StreamDictionary, i);