Test
This commit is contained in:
		
							
								
								
									
										426
									
								
								PrintPDF/PdfSharp/Pdf.Security/MD5Managed.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										426
									
								
								PrintPDF/PdfSharp/Pdf.Security/MD5Managed.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,426 @@
 | 
			
		||||
#region PDFsharp - A .NET library for processing PDF
 | 
			
		||||
//
 | 
			
		||||
// Authors:
 | 
			
		||||
//   Stefan Lange
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
 | 
			
		||||
//
 | 
			
		||||
// http://www.pdfsharp.com
 | 
			
		||||
// http://sourceforge.net/projects/pdfsharp
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
// copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
// to deal in the Software without restriction, including without limitation
 | 
			
		||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
// and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
// Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included
 | 
			
		||||
// in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 | 
			
		||||
// DEALINGS IN THE SOFTWARE.
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
// Based on code from here:
 | 
			
		||||
// http://archive.msdn.microsoft.com/SilverlightMD5/Release/ProjectReleases.aspx?ReleaseId=2206
 | 
			
		||||
//
 | 
			
		||||
// **************************************************************
 | 
			
		||||
// * Raw implementation of the MD5 hash algorithm
 | 
			
		||||
// * from RFC 1321.
 | 
			
		||||
// *
 | 
			
		||||
// * Written By: Reid Borsuk and Jenny Zheng
 | 
			
		||||
// * Copyright (c) Microsoft Corporation.  All rights reserved.
 | 
			
		||||
// **************************************************************
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
#if !NETFX_CORE && !UWP
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// ReSharper disable InconsistentNaming
 | 
			
		||||
 | 
			
		||||
#if SILVERLIGHT || WINDOWS_PHONE || UWP || (GDI && DEBUG)
 | 
			
		||||
namespace PdfSharp.Pdf.Security
 | 
			
		||||
{
 | 
			
		||||
#if UWP
 | 
			
		||||
    class HashAlgorithm
 | 
			
		||||
    {
 | 
			
		||||
        public int HashSizeValue { get; set; }
 | 
			
		||||
 | 
			
		||||
        public virtual void Initialize()
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        protected virtual void HashCore(byte[] array, int ibStart, int cbSize)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        protected virtual byte[] HashFinal()
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public byte[] HashValue { get; set; }
 | 
			
		||||
 | 
			
		||||
        public void TransformBlock(byte[] a, int b, int c, byte[] d, int e)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        public void TransformFinalBlock(byte[] a, int b, int c)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        public byte[] ComputeHash(byte[] a)
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public byte[] Hash
 | 
			
		||||
        {
 | 
			
		||||
            get { return null; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// A managed implementation of the MD5 algorithm.
 | 
			
		||||
    /// Necessary because MD5 is not part of the framework in Silverlight and WP.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    class MD5Managed
 | 
			
		||||
        //#if !UWP
 | 
			
		||||
        : HashAlgorithm  // TODO: WinRT has not even a HashAlgorithm base class.
 | 
			
		||||
                         //#endif
 | 
			
		||||
    {
 | 
			
		||||
        // Intitial values as defined in RFC 1321.
 | 
			
		||||
        const uint A = 0x67452301;
 | 
			
		||||
        const uint B = 0xefcdab89;
 | 
			
		||||
        const uint C = 0x98badcfe;
 | 
			
		||||
        const uint D = 0x10325476;
 | 
			
		||||
 | 
			
		||||
        public MD5Managed()
 | 
			
		||||
        {
 | 
			
		||||
            HashSizeValue = 128;
 | 
			
		||||
            Initialize();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public sealed override void Initialize()
 | 
			
		||||
        {
 | 
			
		||||
            _data = new byte[64];
 | 
			
		||||
            _dataSize = 0;
 | 
			
		||||
            _totalLength = 0;
 | 
			
		||||
            _abcd = new MD5Core.ABCDStruct();
 | 
			
		||||
 | 
			
		||||
            // Intitial values as defined in RFC 1321.
 | 
			
		||||
            _abcd.A = A;
 | 
			
		||||
            _abcd.B = B;
 | 
			
		||||
            _abcd.C = C;
 | 
			
		||||
            _abcd.D = D;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void HashCore(byte[] array, int ibStart, int cbSize)
 | 
			
		||||
        {
 | 
			
		||||
            int startIndex = ibStart;
 | 
			
		||||
            int totalArrayLength = _dataSize + cbSize;
 | 
			
		||||
            if (totalArrayLength >= 64)
 | 
			
		||||
            {
 | 
			
		||||
                Array.Copy(array, startIndex, _data, _dataSize, 64 - _dataSize);
 | 
			
		||||
                // Process message of 64 bytes (512 bits)
 | 
			
		||||
                MD5Core.GetHashBlock(_data, ref _abcd, 0);
 | 
			
		||||
                startIndex += 64 - _dataSize;
 | 
			
		||||
                totalArrayLength -= 64;
 | 
			
		||||
                while (totalArrayLength >= 64)
 | 
			
		||||
                {
 | 
			
		||||
                    Array.Copy(array, startIndex, _data, 0, 64);
 | 
			
		||||
                    MD5Core.GetHashBlock(array, ref _abcd, startIndex);
 | 
			
		||||
                    totalArrayLength -= 64;
 | 
			
		||||
                    startIndex += 64;
 | 
			
		||||
                }
 | 
			
		||||
                _dataSize = totalArrayLength;
 | 
			
		||||
                Array.Copy(array, startIndex, _data, 0, totalArrayLength);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Array.Copy(array, startIndex, _data, _dataSize, cbSize);
 | 
			
		||||
                _dataSize = totalArrayLength;
 | 
			
		||||
            }
 | 
			
		||||
            _totalLength += cbSize;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override byte[] HashFinal()
 | 
			
		||||
        {
 | 
			
		||||
            HashValue = MD5Core.GetHashFinalBlock(_data, 0, _dataSize, _abcd, _totalLength * 8);
 | 
			
		||||
            return HashValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        byte[] _data;
 | 
			
		||||
        MD5Core.ABCDStruct _abcd;
 | 
			
		||||
        Int64 _totalLength;
 | 
			
		||||
        int _dataSize;
 | 
			
		||||
 | 
			
		||||
        static class MD5Core
 | 
			
		||||
        {
 | 
			
		||||
#if true
 | 
			
		||||
            public static byte[] GetHash(byte[] input)
 | 
			
		||||
            {
 | 
			
		||||
                if (null == input)
 | 
			
		||||
                    throw new ArgumentNullException("input");
 | 
			
		||||
 | 
			
		||||
                // Intitial values defined in RFC 1321.
 | 
			
		||||
                ABCDStruct abcd = new ABCDStruct();
 | 
			
		||||
                abcd.A = A;
 | 
			
		||||
                abcd.B = B;
 | 
			
		||||
                abcd.C = C;
 | 
			
		||||
                abcd.D = D;
 | 
			
		||||
 | 
			
		||||
                // We pass in the input array by block, the final block of data must be handled specially for padding & length embeding.
 | 
			
		||||
                int startIndex = 0;
 | 
			
		||||
                while (startIndex <= input.Length - 64)
 | 
			
		||||
                {
 | 
			
		||||
                    GetHashBlock(input, ref abcd, startIndex);
 | 
			
		||||
                    startIndex += 64;
 | 
			
		||||
                }
 | 
			
		||||
                // The final data block. 
 | 
			
		||||
                return GetHashFinalBlock(input, startIndex, input.Length - startIndex, abcd, (Int64)input.Length * 8);
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            internal static byte[] GetHashFinalBlock(byte[] input, int ibStart, int cbSize, ABCDStruct abcd, Int64 len)
 | 
			
		||||
            {
 | 
			
		||||
                byte[] working = new byte[64];
 | 
			
		||||
                byte[] length = BitConverter.GetBytes(len);
 | 
			
		||||
 | 
			
		||||
                // Padding is a single bit 1, followed by the number of 0s required to make size congruent to 448 modulo 512. Step 1 of RFC 1321  
 | 
			
		||||
                // The CLR ensures that our buffer is 0-assigned, we don't need to explicitly set it. This is why it ends up being quicker to just
 | 
			
		||||
                // use a temporary array rather then doing in-place assignment (5% for small inputs)
 | 
			
		||||
                Array.Copy(input, ibStart, working, 0, cbSize);
 | 
			
		||||
                working[cbSize] = 0x80;
 | 
			
		||||
 | 
			
		||||
                // We have enough room to store the length in this chunk.
 | 
			
		||||
                if (cbSize <= 56)
 | 
			
		||||
                {
 | 
			
		||||
                    Array.Copy(length, 0, working, 56, 8);
 | 
			
		||||
                    GetHashBlock(working, ref abcd, 0);
 | 
			
		||||
                }
 | 
			
		||||
                else  // We need an aditional chunk to store the length.
 | 
			
		||||
                {
 | 
			
		||||
                    GetHashBlock(working, ref abcd, 0);
 | 
			
		||||
                    // Create an entirely new chunk due to the 0-assigned trick mentioned above, to avoid an extra function call clearing the array.
 | 
			
		||||
                    working = new byte[64];
 | 
			
		||||
                    Array.Copy(length, 0, working, 56, 8);
 | 
			
		||||
                    GetHashBlock(working, ref abcd, 0);
 | 
			
		||||
                }
 | 
			
		||||
                byte[] output = new byte[16];
 | 
			
		||||
                Array.Copy(BitConverter.GetBytes(abcd.A), 0, output, 0, 4);
 | 
			
		||||
                Array.Copy(BitConverter.GetBytes(abcd.B), 0, output, 4, 4);
 | 
			
		||||
                Array.Copy(BitConverter.GetBytes(abcd.C), 0, output, 8, 4);
 | 
			
		||||
                Array.Copy(BitConverter.GetBytes(abcd.D), 0, output, 12, 4);
 | 
			
		||||
                return output;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            internal static void GetHashBlock(byte[] input, ref ABCDStruct ABCDValue, int ibStart)
 | 
			
		||||
            {
 | 
			
		||||
                uint[] temp = Converter(input, ibStart);
 | 
			
		||||
                uint a = ABCDValue.A;
 | 
			
		||||
                uint b = ABCDValue.B;
 | 
			
		||||
                uint c = ABCDValue.C;
 | 
			
		||||
                uint d = ABCDValue.D;
 | 
			
		||||
 | 
			
		||||
                a = r1(a, b, c, d, temp[0], 7, 0xd76aa478);
 | 
			
		||||
                d = r1(d, a, b, c, temp[1], 12, 0xe8c7b756);
 | 
			
		||||
                c = r1(c, d, a, b, temp[2], 17, 0x242070db);
 | 
			
		||||
                b = r1(b, c, d, a, temp[3], 22, 0xc1bdceee);
 | 
			
		||||
                a = r1(a, b, c, d, temp[4], 7, 0xf57c0faf);
 | 
			
		||||
                d = r1(d, a, b, c, temp[5], 12, 0x4787c62a);
 | 
			
		||||
                c = r1(c, d, a, b, temp[6], 17, 0xa8304613);
 | 
			
		||||
                b = r1(b, c, d, a, temp[7], 22, 0xfd469501);
 | 
			
		||||
                a = r1(a, b, c, d, temp[8], 7, 0x698098d8);
 | 
			
		||||
                d = r1(d, a, b, c, temp[9], 12, 0x8b44f7af);
 | 
			
		||||
                c = r1(c, d, a, b, temp[10], 17, 0xffff5bb1);
 | 
			
		||||
                b = r1(b, c, d, a, temp[11], 22, 0x895cd7be);
 | 
			
		||||
                a = r1(a, b, c, d, temp[12], 7, 0x6b901122);
 | 
			
		||||
                d = r1(d, a, b, c, temp[13], 12, 0xfd987193);
 | 
			
		||||
                c = r1(c, d, a, b, temp[14], 17, 0xa679438e);
 | 
			
		||||
                b = r1(b, c, d, a, temp[15], 22, 0x49b40821);
 | 
			
		||||
 | 
			
		||||
                a = r2(a, b, c, d, temp[1], 5, 0xf61e2562);
 | 
			
		||||
                d = r2(d, a, b, c, temp[6], 9, 0xc040b340);
 | 
			
		||||
                c = r2(c, d, a, b, temp[11], 14, 0x265e5a51);
 | 
			
		||||
                b = r2(b, c, d, a, temp[0], 20, 0xe9b6c7aa);
 | 
			
		||||
                a = r2(a, b, c, d, temp[5], 5, 0xd62f105d);
 | 
			
		||||
                d = r2(d, a, b, c, temp[10], 9, 0x02441453);
 | 
			
		||||
                c = r2(c, d, a, b, temp[15], 14, 0xd8a1e681);
 | 
			
		||||
                b = r2(b, c, d, a, temp[4], 20, 0xe7d3fbc8);
 | 
			
		||||
                a = r2(a, b, c, d, temp[9], 5, 0x21e1cde6);
 | 
			
		||||
                d = r2(d, a, b, c, temp[14], 9, 0xc33707d6);
 | 
			
		||||
                c = r2(c, d, a, b, temp[3], 14, 0xf4d50d87);
 | 
			
		||||
                b = r2(b, c, d, a, temp[8], 20, 0x455a14ed);
 | 
			
		||||
                a = r2(a, b, c, d, temp[13], 5, 0xa9e3e905);
 | 
			
		||||
                d = r2(d, a, b, c, temp[2], 9, 0xfcefa3f8);
 | 
			
		||||
                c = r2(c, d, a, b, temp[7], 14, 0x676f02d9);
 | 
			
		||||
                b = r2(b, c, d, a, temp[12], 20, 0x8d2a4c8a);
 | 
			
		||||
 | 
			
		||||
                a = r3(a, b, c, d, temp[5], 4, 0xfffa3942);
 | 
			
		||||
                d = r3(d, a, b, c, temp[8], 11, 0x8771f681);
 | 
			
		||||
                c = r3(c, d, a, b, temp[11], 16, 0x6d9d6122);
 | 
			
		||||
                b = r3(b, c, d, a, temp[14], 23, 0xfde5380c);
 | 
			
		||||
                a = r3(a, b, c, d, temp[1], 4, 0xa4beea44);
 | 
			
		||||
                d = r3(d, a, b, c, temp[4], 11, 0x4bdecfa9);
 | 
			
		||||
                c = r3(c, d, a, b, temp[7], 16, 0xf6bb4b60);
 | 
			
		||||
                b = r3(b, c, d, a, temp[10], 23, 0xbebfbc70);
 | 
			
		||||
                a = r3(a, b, c, d, temp[13], 4, 0x289b7ec6);
 | 
			
		||||
                d = r3(d, a, b, c, temp[0], 11, 0xeaa127fa);
 | 
			
		||||
                c = r3(c, d, a, b, temp[3], 16, 0xd4ef3085);
 | 
			
		||||
                b = r3(b, c, d, a, temp[6], 23, 0x04881d05);
 | 
			
		||||
                a = r3(a, b, c, d, temp[9], 4, 0xd9d4d039);
 | 
			
		||||
                d = r3(d, a, b, c, temp[12], 11, 0xe6db99e5);
 | 
			
		||||
                c = r3(c, d, a, b, temp[15], 16, 0x1fa27cf8);
 | 
			
		||||
                b = r3(b, c, d, a, temp[2], 23, 0xc4ac5665);
 | 
			
		||||
 | 
			
		||||
                a = r4(a, b, c, d, temp[0], 6, 0xf4292244);
 | 
			
		||||
                d = r4(d, a, b, c, temp[7], 10, 0x432aff97);
 | 
			
		||||
                c = r4(c, d, a, b, temp[14], 15, 0xab9423a7);
 | 
			
		||||
                b = r4(b, c, d, a, temp[5], 21, 0xfc93a039);
 | 
			
		||||
                a = r4(a, b, c, d, temp[12], 6, 0x655b59c3);
 | 
			
		||||
                d = r4(d, a, b, c, temp[3], 10, 0x8f0ccc92);
 | 
			
		||||
                c = r4(c, d, a, b, temp[10], 15, 0xffeff47d);
 | 
			
		||||
                b = r4(b, c, d, a, temp[1], 21, 0x85845dd1);
 | 
			
		||||
                a = r4(a, b, c, d, temp[8], 6, 0x6fa87e4f);
 | 
			
		||||
                d = r4(d, a, b, c, temp[15], 10, 0xfe2ce6e0);
 | 
			
		||||
                c = r4(c, d, a, b, temp[6], 15, 0xa3014314);
 | 
			
		||||
                b = r4(b, c, d, a, temp[13], 21, 0x4e0811a1);
 | 
			
		||||
                a = r4(a, b, c, d, temp[4], 6, 0xf7537e82);
 | 
			
		||||
                d = r4(d, a, b, c, temp[11], 10, 0xbd3af235);
 | 
			
		||||
                c = r4(c, d, a, b, temp[2], 15, 0x2ad7d2bb);
 | 
			
		||||
                b = r4(b, c, d, a, temp[9], 21, 0xeb86d391);
 | 
			
		||||
 | 
			
		||||
                ABCDValue.A = unchecked(a + ABCDValue.A);
 | 
			
		||||
                ABCDValue.B = unchecked(b + ABCDValue.B);
 | 
			
		||||
                ABCDValue.C = unchecked(c + ABCDValue.C);
 | 
			
		||||
                ABCDValue.D = unchecked(d + ABCDValue.D);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Manually unrolling these equations nets us a 20% performance improvement
 | 
			
		||||
            private static uint r1(uint a, uint b, uint c, uint d, uint x, int s, uint t)
 | 
			
		||||
            {
 | 
			
		||||
                //                  (b + LSR((a + F(b, c, d) + x + t), s))
 | 
			
		||||
                // F(x, y, z)        ((x & y) | ((x ^ 0xFFFFFFFF) & z))
 | 
			
		||||
                return unchecked(b + LSR((a + ((b & c) | ((b ^ 0xFFFFFFFF) & d)) + x + t), s));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private static uint r2(uint a, uint b, uint c, uint d, uint x, int s, uint t)
 | 
			
		||||
            {
 | 
			
		||||
                //                   (b + LSR((a + G(b, c, d) + x + t), s))
 | 
			
		||||
                // G(x, y, z)        ((x & z) | (y & (z ^ 0xFFFFFFFF)))
 | 
			
		||||
                return unchecked(b + LSR((a + ((b & d) | (c & (d ^ 0xFFFFFFFF))) + x + t), s));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private static uint r3(uint a, uint b, uint c, uint d, uint x, int s, uint t)
 | 
			
		||||
            {
 | 
			
		||||
                //                   (b + LSR((a + H(b, c, d) + k + i), s))
 | 
			
		||||
                // H(x, y, z)        (x ^ y ^ z)
 | 
			
		||||
                return unchecked(b + LSR((a + (b ^ c ^ d) + x + t), s));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private static uint r4(uint a, uint b, uint c, uint d, uint x, int s, uint t)
 | 
			
		||||
            {
 | 
			
		||||
                //                   (b + LSR((a + I(b, c, d) + k + i), s))
 | 
			
		||||
                // I(x, y, z)        (y ^ (x | (z ^ 0xFFFFFFFF)))
 | 
			
		||||
                return unchecked(b + LSR((a + (c ^ (b | (d ^ 0xFFFFFFFF))) + x + t), s));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Implementation of left rotate
 | 
			
		||||
            // s is an int instead of a uint becuase the CLR requires the argument passed to >>/<< is of 
 | 
			
		||||
            // type int. Doing the demoting inside this function would add overhead.
 | 
			
		||||
            private static uint LSR(uint i, int s)
 | 
			
		||||
            {
 | 
			
		||||
                return (i << s) | (i >> (32 - s));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Convert input array into array of UInts.
 | 
			
		||||
            static uint[] Converter(byte[] input, int ibStart)
 | 
			
		||||
            {
 | 
			
		||||
                if (null == input)
 | 
			
		||||
                    throw new ArgumentNullException("input");
 | 
			
		||||
 | 
			
		||||
                uint[] result = new uint[16];
 | 
			
		||||
                for (int idx = 0; idx < 16; idx++)
 | 
			
		||||
                {
 | 
			
		||||
                    result[idx] = (uint)input[ibStart + idx * 4];
 | 
			
		||||
                    result[idx] += (uint)input[ibStart + idx * 4 + 1] << 8;
 | 
			
		||||
                    result[idx] += (uint)input[ibStart + idx * 4 + 2] << 16;
 | 
			
		||||
                    result[idx] += (uint)input[ibStart + idx * 4 + 3] << 24;
 | 
			
		||||
 | 
			
		||||
                    Debug.Assert(result[idx] ==
 | 
			
		||||
                      (input[ibStart + idx * 4]) +
 | 
			
		||||
                      ((uint)input[ibStart + idx * 4 + 1] << 8) +
 | 
			
		||||
                      ((uint)input[ibStart + idx * 4 + 2] << 16) +
 | 
			
		||||
                      ((uint)input[ibStart + idx * 4 + 3] << 24));
 | 
			
		||||
                }
 | 
			
		||||
                return result;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Simple struct for the (a,b,c,d) which is used to compute the mesage digest.    
 | 
			
		||||
            public struct ABCDStruct
 | 
			
		||||
            {
 | 
			
		||||
                public uint A;
 | 
			
		||||
                public uint B;
 | 
			
		||||
                public uint C;
 | 
			
		||||
                public uint D;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if GDI && DEBUG && true_
 | 
			
		||||
 | 
			
		||||
    // See here for details: http://archive.msdn.microsoft.com/SilverlightMD5/WorkItem/View.aspx?WorkItemId=3
 | 
			
		||||
 | 
			
		||||
    public static class TestMD5
 | 
			
		||||
    {
 | 
			
		||||
        public static void Test()
 | 
			
		||||
        {
 | 
			
		||||
            Random rnd = new Random();
 | 
			
		||||
            for (int i = 0; i < 10000; i++)
 | 
			
		||||
            {
 | 
			
		||||
                int count = rnd.Next(1000) + 1;
 | 
			
		||||
                Console.WriteLine(String.Format("{0}: {1}", i, count));
 | 
			
		||||
                Test2(count);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static void Test2(int count)
 | 
			
		||||
        {
 | 
			
		||||
            byte[] bytes = new byte[count];
 | 
			
		||||
 | 
			
		||||
            for (int idx = 0; idx < count; idx += 16)
 | 
			
		||||
                Array.Copy(Guid.NewGuid().ToByteArray(), 0, bytes, idx, Math.Min(16, count - idx));
 | 
			
		||||
 | 
			
		||||
            MD5 md5dotNet = new MD5CryptoServiceProvider();
 | 
			
		||||
            md5dotNet.Initialize();
 | 
			
		||||
            MD5Managed md5m = new MD5Managed();
 | 
			
		||||
            md5m.Initialize();
 | 
			
		||||
 | 
			
		||||
            byte[] result1 = md5dotNet.ComputeHash(bytes);
 | 
			
		||||
            byte[] result2 = md5m.ComputeHash(bytes);
 | 
			
		||||
 | 
			
		||||
            if (!CompareBytes(result1, result2))
 | 
			
		||||
            {
 | 
			
		||||
                count.GetType();
 | 
			
		||||
                //throw new Exception("Bug in MD5Managed...");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static bool CompareBytes(byte[] bytes1, byte[] bytes2)
 | 
			
		||||
        {
 | 
			
		||||
            for (int idx = 0; idx < bytes1.Length; idx++)
 | 
			
		||||
            {
 | 
			
		||||
                if (bytes1[idx] != bytes2[idx])
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										137
									
								
								PrintPDF/PdfSharp/Pdf.Security/PdfSecurityHandler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								PrintPDF/PdfSharp/Pdf.Security/PdfSecurityHandler.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,137 @@
 | 
			
		||||
#region PDFsharp - A .NET library for processing PDF
 | 
			
		||||
//
 | 
			
		||||
// Authors:
 | 
			
		||||
//   Stefan Lange
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
 | 
			
		||||
//
 | 
			
		||||
// http://www.pdfsharp.com
 | 
			
		||||
// http://sourceforge.net/projects/pdfsharp
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
// copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
// to deal in the Software without restriction, including without limitation
 | 
			
		||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
// and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
// Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included
 | 
			
		||||
// in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 | 
			
		||||
// DEALINGS IN THE SOFTWARE.
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
// ReSharper disable InconsistentNaming
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.Pdf.Security
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Represents the base of all security handlers.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract class PdfSecurityHandler : PdfDictionary
 | 
			
		||||
    {
 | 
			
		||||
        internal PdfSecurityHandler(PdfDocument document)
 | 
			
		||||
            : base(document)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        internal PdfSecurityHandler(PdfDictionary dict)
 | 
			
		||||
            : base(dict)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Predefined keys of this dictionary.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal class Keys : KeysBase
 | 
			
		||||
        {
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Required) The name of the preferred security handler for this document. Typically,
 | 
			
		||||
            /// it is the name of the security handler that was used to encrypt the document. If 
 | 
			
		||||
            /// SubFilter is not present, only this security handler should be used when opening 
 | 
			
		||||
            /// the document. If it is present, consumer applications can use any security handler
 | 
			
		||||
            /// that implements the format specified by SubFilter.
 | 
			
		||||
            /// Standard is the name of the built-in password-based security handler. Names for other
 | 
			
		||||
            /// security handlers can be registered by using the procedure described in Appendix E.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo(KeyType.Name | KeyType.Required)]
 | 
			
		||||
            public const string Filter = "/Filter";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Optional; PDF 1.3) A name that completely specifies the format and interpretation of
 | 
			
		||||
            /// the contents of the encryption dictionary. It is needed to allow security handlers other
 | 
			
		||||
            /// than the one specified by Filter to decrypt the document. If this entry is absent, other
 | 
			
		||||
            /// security handlers should not be allowed to decrypt the document.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo("1.3", KeyType.Name | KeyType.Optional)]
 | 
			
		||||
            public const string SubFilter = "/SubFilter";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Optional but strongly recommended) A code specifying the algorithm to be used in encrypting
 | 
			
		||||
            /// and decrypting the document:
 | 
			
		||||
            /// 0 An algorithm that is undocumented and no longer supported, and whose use is strongly discouraged.
 | 
			
		||||
            /// 1 Algorithm 3.1, with an encryption key length of 40 bits.
 | 
			
		||||
            /// 2 (PDF 1.4) Algorithm 3.1, but permitting encryption key lengths greater than 40 bits.
 | 
			
		||||
            /// 3 (PDF 1.4) An unpublished algorithm that permits encryption key lengths ranging from 40 to 128 bits.
 | 
			
		||||
            /// 4 (PDF 1.5) The security handler defines the use of encryption and decryption in the document, using
 | 
			
		||||
            ///             the rules specified by the CF, StmF, and StrF entries.
 | 
			
		||||
            /// The default value if this entry is omitted is 0, but a value of 1 or greater is strongly recommended.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo(KeyType.Integer | KeyType.Optional)]
 | 
			
		||||
            public const string V = "/V";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Optional; PDF 1.4; only if V is 2 or 3) The length of the encryption key, in bits.
 | 
			
		||||
            /// The value must be a multiple of 8, in the range 40 to 128. Default value: 40.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo("1.4", KeyType.Integer | KeyType.Optional)]
 | 
			
		||||
            public const string Length = "/Length";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Optional; meaningful only when the value of V is 4; PDF 1.5)
 | 
			
		||||
            /// A dictionary whose keys are crypt filter names and whose values are the corresponding
 | 
			
		||||
            /// crypt filter dictionaries. Every crypt filter used in the document must have an entry
 | 
			
		||||
            /// in this dictionary, except for the standard crypt filter names.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo(KeyType.Dictionary | KeyType.Optional)]
 | 
			
		||||
            public const string CF = "/CF";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Optional; meaningful only when the value of V is 4; PDF 1.5)
 | 
			
		||||
            /// The name of the crypt filter that is used by default when decrypting streams.
 | 
			
		||||
            /// The name must be a key in the CF dictionary or a standard crypt filter name. All streams
 | 
			
		||||
            /// in the document, except for cross-reference streams or streams that have a Crypt entry in
 | 
			
		||||
            /// their Filter array, are decrypted by the security handler, using this crypt filter.
 | 
			
		||||
            /// Default value: Identity.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo("1.5", KeyType.Name | KeyType.Optional)]
 | 
			
		||||
            public const string StmF = "/StmF";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Optional; meaningful only when the value of V is 4; PDF 1.)
 | 
			
		||||
            /// The name of the crypt filter that is used when decrypting all strings in the document.
 | 
			
		||||
            /// The name must be a key in the CF dictionary or a standard crypt filter name.
 | 
			
		||||
            /// Default value: Identity.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo("1.5", KeyType.Name | KeyType.Optional)]
 | 
			
		||||
            public const string StrF = "/StrF";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Optional; meaningful only when the value of V is 4; PDF 1.6)
 | 
			
		||||
            /// The name of the crypt filter that should be used by default when encrypting embedded
 | 
			
		||||
            /// file streams; it must correspond to a key in the CF dictionary or a standard crypt
 | 
			
		||||
            /// filter name. This entry is provided by the security handler. Applications should respect
 | 
			
		||||
            /// this value when encrypting embedded files, except for embedded file streams that have
 | 
			
		||||
            /// their own crypt filter specifier. If this entry is not present, and the embedded file
 | 
			
		||||
            /// stream does not contain a crypt filter specifier, the stream should be encrypted using
 | 
			
		||||
            /// the default stream crypt filter specified by StmF.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo("1.6", KeyType.Name | KeyType.Optional)]
 | 
			
		||||
            public const string EFF = "/EFF";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										253
									
								
								PrintPDF/PdfSharp/Pdf.Security/PdfSecuritySettings.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								PrintPDF/PdfSharp/Pdf.Security/PdfSecuritySettings.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,253 @@
 | 
			
		||||
#region PDFsharp - A .NET library for processing PDF
 | 
			
		||||
//
 | 
			
		||||
// Authors:
 | 
			
		||||
//   Stefan Lange
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
 | 
			
		||||
//
 | 
			
		||||
// http://www.pdfsharp.com
 | 
			
		||||
// http://sourceforge.net/projects/pdfsharp
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
// copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
// to deal in the Software without restriction, including without limitation
 | 
			
		||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
// and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
// Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included
 | 
			
		||||
// in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 | 
			
		||||
// DEALINGS IN THE SOFTWARE.
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.Pdf.Security
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Encapsulates access to the security settings of a PDF document.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public sealed class PdfSecuritySettings
 | 
			
		||||
    {
 | 
			
		||||
        internal PdfSecuritySettings(PdfDocument document)
 | 
			
		||||
        {
 | 
			
		||||
            _document = document;
 | 
			
		||||
        }
 | 
			
		||||
        readonly PdfDocument _document;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Indicates whether the granted access to the document is 'owner permission'. Returns true if the document 
 | 
			
		||||
        /// is unprotected or was opened with the owner password. Returns false if the document was opened with the
 | 
			
		||||
        /// user password.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool HasOwnerPermissions
 | 
			
		||||
        {
 | 
			
		||||
            get { return _hasOwnerPermissions; }
 | 
			
		||||
        }
 | 
			
		||||
        internal bool _hasOwnerPermissions = true;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the document security level. If you set the security level to anything but PdfDocumentSecurityLevel.None
 | 
			
		||||
        /// you must also set a user and/or an owner password. Otherwise saving the document will fail.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public PdfDocumentSecurityLevel DocumentSecurityLevel
 | 
			
		||||
        {
 | 
			
		||||
            get { return _documentSecurityLevel; }
 | 
			
		||||
            set { _documentSecurityLevel = value; }
 | 
			
		||||
        }
 | 
			
		||||
        PdfDocumentSecurityLevel _documentSecurityLevel;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the user password of the document. Setting a password automatically sets the
 | 
			
		||||
        /// PdfDocumentSecurityLevel to PdfDocumentSecurityLevel.Encrypted128Bit if its current
 | 
			
		||||
        /// value is PdfDocumentSecurityLevel.None.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string UserPassword
 | 
			
		||||
        {
 | 
			
		||||
            set { SecurityHandler.UserPassword = value; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the owner password of the document. Setting a password automatically sets the
 | 
			
		||||
        /// PdfDocumentSecurityLevel to PdfDocumentSecurityLevel.Encrypted128Bit if its current
 | 
			
		||||
        /// value is PdfDocumentSecurityLevel.None.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string OwnerPassword
 | 
			
		||||
        {
 | 
			
		||||
            set { SecurityHandler.OwnerPassword = value; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Determines whether the document can be saved.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal bool CanSave(ref string message)
 | 
			
		||||
        {
 | 
			
		||||
            if (_documentSecurityLevel != PdfDocumentSecurityLevel.None)
 | 
			
		||||
            {
 | 
			
		||||
                if (String.IsNullOrEmpty(SecurityHandler._userPassword) && String.IsNullOrEmpty(SecurityHandler._ownerPassword))
 | 
			
		||||
                {
 | 
			
		||||
                    message = PSSR.UserOrOwnerPasswordRequired;
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Permissions
 | 
			
		||||
        //TODO: Use documentation from our English Acrobat 6.0 version.
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits printing the document. Should be used in conjunction with PermitFullQualityPrint.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool PermitPrint
 | 
			
		||||
        {
 | 
			
		||||
            get { return (SecurityHandler.Permission & PdfUserAccessPermission.PermitPrint) != 0; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = SecurityHandler.Permission;
 | 
			
		||||
                if (value)
 | 
			
		||||
                    permission |= PdfUserAccessPermission.PermitPrint;
 | 
			
		||||
                else
 | 
			
		||||
                    permission &= ~PdfUserAccessPermission.PermitPrint;
 | 
			
		||||
                SecurityHandler.Permission = permission;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits modifying the document.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool PermitModifyDocument
 | 
			
		||||
        {
 | 
			
		||||
            get { return (SecurityHandler.Permission & PdfUserAccessPermission.PermitModifyDocument) != 0; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = SecurityHandler.Permission;
 | 
			
		||||
                if (value)
 | 
			
		||||
                    permission |= PdfUserAccessPermission.PermitModifyDocument;
 | 
			
		||||
                else
 | 
			
		||||
                    permission &= ~PdfUserAccessPermission.PermitModifyDocument;
 | 
			
		||||
                SecurityHandler.Permission = permission;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits content copying or extraction.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool PermitExtractContent
 | 
			
		||||
        {
 | 
			
		||||
            get { return (SecurityHandler.Permission & PdfUserAccessPermission.PermitExtractContent) != 0; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = SecurityHandler.Permission;
 | 
			
		||||
                if (value)
 | 
			
		||||
                    permission |= PdfUserAccessPermission.PermitExtractContent;
 | 
			
		||||
                else
 | 
			
		||||
                    permission &= ~PdfUserAccessPermission.PermitExtractContent;
 | 
			
		||||
                SecurityHandler.Permission = permission;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits commenting the document.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool PermitAnnotations
 | 
			
		||||
        {
 | 
			
		||||
            get { return (SecurityHandler.Permission & PdfUserAccessPermission.PermitAnnotations) != 0; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = SecurityHandler.Permission;
 | 
			
		||||
                if (value)
 | 
			
		||||
                    permission |= PdfUserAccessPermission.PermitAnnotations;
 | 
			
		||||
                else
 | 
			
		||||
                    permission &= ~PdfUserAccessPermission.PermitAnnotations;
 | 
			
		||||
                SecurityHandler.Permission = permission;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits filling of form fields.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool PermitFormsFill
 | 
			
		||||
        {
 | 
			
		||||
            get { return (SecurityHandler.Permission & PdfUserAccessPermission.PermitFormsFill) != 0; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = SecurityHandler.Permission;
 | 
			
		||||
                if (value)
 | 
			
		||||
                    permission |= PdfUserAccessPermission.PermitFormsFill;
 | 
			
		||||
                else
 | 
			
		||||
                    permission &= ~PdfUserAccessPermission.PermitFormsFill;
 | 
			
		||||
                SecurityHandler.Permission = permission;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits content extraction for accessibility.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool PermitAccessibilityExtractContent
 | 
			
		||||
        {
 | 
			
		||||
            get { return (SecurityHandler.Permission & PdfUserAccessPermission.PermitAccessibilityExtractContent) != 0; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = SecurityHandler.Permission;
 | 
			
		||||
                if (value)
 | 
			
		||||
                    permission |= PdfUserAccessPermission.PermitAccessibilityExtractContent;
 | 
			
		||||
                else
 | 
			
		||||
                    permission &= ~PdfUserAccessPermission.PermitAccessibilityExtractContent;
 | 
			
		||||
                SecurityHandler.Permission = permission;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits to insert, rotate, or delete pages and create bookmarks or thumbnail images even if
 | 
			
		||||
        /// PermitModifyDocument is not set.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool PermitAssembleDocument
 | 
			
		||||
        {
 | 
			
		||||
            get { return (SecurityHandler.Permission & PdfUserAccessPermission.PermitAssembleDocument) != 0; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = SecurityHandler.Permission;
 | 
			
		||||
                if (value)
 | 
			
		||||
                    permission |= PdfUserAccessPermission.PermitAssembleDocument;
 | 
			
		||||
                else
 | 
			
		||||
                    permission &= ~PdfUserAccessPermission.PermitAssembleDocument;
 | 
			
		||||
                SecurityHandler.Permission = permission;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits to print in high quality. insert, rotate, or delete pages and create bookmarks or thumbnail images
 | 
			
		||||
        /// even if PermitModifyDocument is not set.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool PermitFullQualityPrint
 | 
			
		||||
        {
 | 
			
		||||
            get { return (SecurityHandler.Permission & PdfUserAccessPermission.PermitFullQualityPrint) != 0; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = SecurityHandler.Permission;
 | 
			
		||||
                if (value)
 | 
			
		||||
                    permission |= PdfUserAccessPermission.PermitFullQualityPrint;
 | 
			
		||||
                else
 | 
			
		||||
                    permission &= ~PdfUserAccessPermission.PermitFullQualityPrint;
 | 
			
		||||
                SecurityHandler.Permission = permission;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// PdfStandardSecurityHandler is the only implemented handler.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal PdfStandardSecurityHandler SecurityHandler
 | 
			
		||||
        {
 | 
			
		||||
            get { return _document._trailer.SecurityHandler; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										737
									
								
								PrintPDF/PdfSharp/Pdf.Security/PdfStandardSecurityHandler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										737
									
								
								PrintPDF/PdfSharp/Pdf.Security/PdfStandardSecurityHandler.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,737 @@
 | 
			
		||||
#region PDFsharp - A .NET library for processing PDF
 | 
			
		||||
//
 | 
			
		||||
// Authors:
 | 
			
		||||
//   Stefan Lange
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
 | 
			
		||||
//
 | 
			
		||||
// http://www.pdfsharp.com
 | 
			
		||||
// http://sourceforge.net/projects/pdfsharp
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
// copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
// to deal in the Software without restriction, including without limitation
 | 
			
		||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
// and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
// Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included
 | 
			
		||||
// in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 | 
			
		||||
// DEALINGS IN THE SOFTWARE.
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using PdfSharp.Pdf;
 | 
			
		||||
using PdfSharp.Pdf.IO;
 | 
			
		||||
using PdfSharp.Pdf.Advanced;
 | 
			
		||||
using PdfSharp.Pdf.Internal;
 | 
			
		||||
#if !NETFX_CORE && !UWP
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#pragma warning disable 0169
 | 
			
		||||
#pragma warning disable 0649
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.Pdf.Security
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Represents the standard PDF security handler.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public sealed class PdfStandardSecurityHandler : PdfSecurityHandler
 | 
			
		||||
    {
 | 
			
		||||
        internal PdfStandardSecurityHandler(PdfDocument document)
 | 
			
		||||
            : base(document)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        internal PdfStandardSecurityHandler(PdfDictionary dict)
 | 
			
		||||
            : base(dict)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the user password of the document. Setting a password automatically sets the
 | 
			
		||||
        /// PdfDocumentSecurityLevel to PdfDocumentSecurityLevel.Encrypted128Bit if its current
 | 
			
		||||
        /// value is PdfDocumentSecurityLevel.None.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string UserPassword
 | 
			
		||||
        {
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                if (_document._securitySettings.DocumentSecurityLevel == PdfDocumentSecurityLevel.None)
 | 
			
		||||
                    _document._securitySettings.DocumentSecurityLevel = PdfDocumentSecurityLevel.Encrypted128Bit;
 | 
			
		||||
                _userPassword = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        internal string _userPassword;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the owner password of the document. Setting a password automatically sets the
 | 
			
		||||
        /// PdfDocumentSecurityLevel to PdfDocumentSecurityLevel.Encrypted128Bit if its current
 | 
			
		||||
        /// value is PdfDocumentSecurityLevel.None.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string OwnerPassword
 | 
			
		||||
        {
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                if (_document._securitySettings.DocumentSecurityLevel == PdfDocumentSecurityLevel.None)
 | 
			
		||||
                    _document._securitySettings.DocumentSecurityLevel = PdfDocumentSecurityLevel.Encrypted128Bit;
 | 
			
		||||
                _ownerPassword = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        internal string _ownerPassword;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the user access permission represented as an integer in the P key.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal PdfUserAccessPermission Permission
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                PdfUserAccessPermission permission = (PdfUserAccessPermission)Elements.GetInteger(Keys.P);
 | 
			
		||||
                if ((int)permission == 0)
 | 
			
		||||
                    permission = PdfUserAccessPermission.PermitAll;
 | 
			
		||||
                return permission;
 | 
			
		||||
            }
 | 
			
		||||
            set { Elements.SetInteger(Keys.P, (int)value); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts the whole document.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void EncryptDocument()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (PdfReference iref in _document._irefTable.AllReferences)
 | 
			
		||||
            {
 | 
			
		||||
                if (!ReferenceEquals(iref.Value, this))
 | 
			
		||||
                    EncryptObject(iref.Value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts an indirect object.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal void EncryptObject(PdfObject value)
 | 
			
		||||
        {
 | 
			
		||||
            Debug.Assert(value.Reference != null);
 | 
			
		||||
 | 
			
		||||
            SetHashKey(value.ObjectID);
 | 
			
		||||
#if DEBUG
 | 
			
		||||
            if (value.ObjectID.ObjectNumber == 10)
 | 
			
		||||
                GetType();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            PdfDictionary dict;
 | 
			
		||||
            PdfArray array;
 | 
			
		||||
            PdfStringObject str;
 | 
			
		||||
            if ((dict = value as PdfDictionary) != null)
 | 
			
		||||
                EncryptDictionary(dict);
 | 
			
		||||
            else if ((array = value as PdfArray) != null)
 | 
			
		||||
                EncryptArray(array);
 | 
			
		||||
            else if ((str = value as PdfStringObject) != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (str.Length != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    byte[] bytes = str.EncryptionValue;
 | 
			
		||||
                    PrepareKey();
 | 
			
		||||
                    EncryptRC4(bytes);
 | 
			
		||||
                    str.EncryptionValue = bytes;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts a dictionary.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void EncryptDictionary(PdfDictionary dict)
 | 
			
		||||
        {
 | 
			
		||||
            PdfName[] names = dict.Elements.KeyNames;
 | 
			
		||||
            foreach (KeyValuePair<string, PdfItem> item in dict.Elements)
 | 
			
		||||
            {
 | 
			
		||||
                PdfString value1;
 | 
			
		||||
                PdfDictionary value2;
 | 
			
		||||
                PdfArray value3;
 | 
			
		||||
                if ((value1 = item.Value as PdfString) != null)
 | 
			
		||||
                    EncryptString(value1);
 | 
			
		||||
                else if ((value2 = item.Value as PdfDictionary) != null)
 | 
			
		||||
                    EncryptDictionary(value2);
 | 
			
		||||
                else if ((value3 = item.Value as PdfArray) != null)
 | 
			
		||||
                    EncryptArray(value3);
 | 
			
		||||
            }
 | 
			
		||||
            if (dict.Stream != null)
 | 
			
		||||
            {
 | 
			
		||||
                byte[] bytes = dict.Stream.Value;
 | 
			
		||||
                if (bytes.Length != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    PrepareKey();
 | 
			
		||||
                    EncryptRC4(bytes);
 | 
			
		||||
                    dict.Stream.Value = bytes;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts an array.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void EncryptArray(PdfArray array)
 | 
			
		||||
        {
 | 
			
		||||
            int count = array.Elements.Count;
 | 
			
		||||
            for (int idx = 0; idx < count; idx++)
 | 
			
		||||
            {
 | 
			
		||||
                PdfItem item = array.Elements[idx];
 | 
			
		||||
                PdfString value1;
 | 
			
		||||
                PdfDictionary value2;
 | 
			
		||||
                PdfArray value3;
 | 
			
		||||
                if ((value1 = item as PdfString) != null)
 | 
			
		||||
                    EncryptString(value1);
 | 
			
		||||
                else if ((value2 = item as PdfDictionary) != null)
 | 
			
		||||
                    EncryptDictionary(value2);
 | 
			
		||||
                else if ((value3 = item as PdfArray) != null)
 | 
			
		||||
                    EncryptArray(value3);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts a string.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void EncryptString(PdfString value)
 | 
			
		||||
        {
 | 
			
		||||
            if (value.Length != 0)
 | 
			
		||||
            {
 | 
			
		||||
                byte[] bytes = value.EncryptionValue;
 | 
			
		||||
                PrepareKey();
 | 
			
		||||
                EncryptRC4(bytes);
 | 
			
		||||
                value.EncryptionValue = bytes;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts an array.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal byte[] EncryptBytes(byte[] bytes)
 | 
			
		||||
        {
 | 
			
		||||
            if (bytes != null && bytes.Length != 0)
 | 
			
		||||
            {
 | 
			
		||||
                PrepareKey();
 | 
			
		||||
                EncryptRC4(bytes);
 | 
			
		||||
            }
 | 
			
		||||
            return bytes;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Encryption Algorithms
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Checks the password.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="inputPassword">Password or null if no password is provided.</param>
 | 
			
		||||
        public PasswordValidity ValidatePassword(string inputPassword)
 | 
			
		||||
        {
 | 
			
		||||
            // We can handle 40 and 128 bit standard encryption.
 | 
			
		||||
            string filter = Elements.GetName(PdfSecurityHandler.Keys.Filter);
 | 
			
		||||
            int v = Elements.GetInteger(PdfSecurityHandler.Keys.V);
 | 
			
		||||
            if (filter != "/Standard" || !(v >= 1 && v <= 3))
 | 
			
		||||
                throw new PdfReaderException(PSSR.UnknownEncryption);
 | 
			
		||||
 | 
			
		||||
            byte[] documentID = PdfEncoders.RawEncoding.GetBytes(Owner.Internals.FirstDocumentID);
 | 
			
		||||
            byte[] oValue = PdfEncoders.RawEncoding.GetBytes(Elements.GetString(Keys.O));
 | 
			
		||||
            byte[] uValue = PdfEncoders.RawEncoding.GetBytes(Elements.GetString(Keys.U));
 | 
			
		||||
            int pValue = Elements.GetInteger(Keys.P);
 | 
			
		||||
            int rValue = Elements.GetInteger(Keys.R);
 | 
			
		||||
 | 
			
		||||
            if (inputPassword == null)
 | 
			
		||||
                inputPassword = "";
 | 
			
		||||
 | 
			
		||||
            bool strongEncryption = rValue == 3;
 | 
			
		||||
            int keyLength = strongEncryption ? 16 : 32;
 | 
			
		||||
 | 
			
		||||
            // Try owner password first.
 | 
			
		||||
            //byte[] password = PdfEncoders.RawEncoding.GetBytes(inputPassword);
 | 
			
		||||
            InitWithOwnerPassword(documentID, inputPassword, oValue, pValue, strongEncryption);
 | 
			
		||||
            if (EqualsKey(uValue, keyLength))
 | 
			
		||||
            {
 | 
			
		||||
                _document.SecuritySettings._hasOwnerPermissions = true;
 | 
			
		||||
                return PasswordValidity.OwnerPassword;
 | 
			
		||||
            }
 | 
			
		||||
            _document.SecuritySettings._hasOwnerPermissions = false;
 | 
			
		||||
 | 
			
		||||
            // Now try user password.
 | 
			
		||||
            //password = PdfEncoders.RawEncoding.GetBytes(inputPassword);
 | 
			
		||||
            InitWithUserPassword(documentID, inputPassword, oValue, pValue, strongEncryption);
 | 
			
		||||
            if (EqualsKey(uValue, keyLength))
 | 
			
		||||
                return PasswordValidity.UserPassword;
 | 
			
		||||
            return PasswordValidity.Invalid;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Conditional("DEBUG")]
 | 
			
		||||
        static void DumpBytes(string tag, byte[] bytes)
 | 
			
		||||
        {
 | 
			
		||||
            string dump = tag + ": ";
 | 
			
		||||
            for (int idx = 0; idx < bytes.Length; idx++)
 | 
			
		||||
                dump += String.Format("{0:X2}", bytes[idx]);
 | 
			
		||||
            Debug.WriteLine(dump);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Pads a password to a 32 byte array.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        static byte[] PadPassword(string password)
 | 
			
		||||
        {
 | 
			
		||||
            byte[] padded = new byte[32];
 | 
			
		||||
            if (password == null)
 | 
			
		||||
                Array.Copy(PasswordPadding, 0, padded, 0, 32);
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                int length = password.Length;
 | 
			
		||||
                Array.Copy(PdfEncoders.RawEncoding.GetBytes(password), 0, padded, 0, Math.Min(length, 32));
 | 
			
		||||
                if (length < 32)
 | 
			
		||||
                    Array.Copy(PasswordPadding, 0, padded, length, 32 - length);
 | 
			
		||||
            }
 | 
			
		||||
            return padded;
 | 
			
		||||
        }
 | 
			
		||||
        static readonly byte[] PasswordPadding = // 32 bytes password padding defined by Adobe
 | 
			
		||||
            {
 | 
			
		||||
              0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
 | 
			
		||||
              0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Generates the user key based on the padded user password.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void InitWithUserPassword(byte[] documentID, string userPassword, byte[] ownerKey, int permissions, bool strongEncryption)
 | 
			
		||||
        {
 | 
			
		||||
            InitEncryptionKey(documentID, PadPassword(userPassword), ownerKey, permissions, strongEncryption);
 | 
			
		||||
            SetupUserKey(documentID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Generates the user key based on the padded owner password.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void InitWithOwnerPassword(byte[] documentID, string ownerPassword, byte[] ownerKey, int permissions, bool strongEncryption)
 | 
			
		||||
        {
 | 
			
		||||
            byte[] userPad = ComputeOwnerKey(ownerKey, PadPassword(ownerPassword), strongEncryption);
 | 
			
		||||
            InitEncryptionKey(documentID, userPad, ownerKey, permissions, strongEncryption);
 | 
			
		||||
            SetupUserKey(documentID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Computes the padded user password from the padded owner password.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        byte[] ComputeOwnerKey(byte[] userPad, byte[] ownerPad, bool strongEncryption)
 | 
			
		||||
        {
 | 
			
		||||
            byte[] ownerKey = new byte[32];
 | 
			
		||||
            //#if !SILVERLIGHT
 | 
			
		||||
            byte[] digest = _md5.ComputeHash(ownerPad);
 | 
			
		||||
            if (strongEncryption)
 | 
			
		||||
            {
 | 
			
		||||
                byte[] mkey = new byte[16];
 | 
			
		||||
                // Hash the pad 50 times
 | 
			
		||||
                for (int idx = 0; idx < 50; idx++)
 | 
			
		||||
                    digest = _md5.ComputeHash(digest);
 | 
			
		||||
                Array.Copy(userPad, 0, ownerKey, 0, 32);
 | 
			
		||||
                // Encrypt the key
 | 
			
		||||
                for (int i = 0; i < 20; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    for (int j = 0; j < mkey.Length; ++j)
 | 
			
		||||
                        mkey[j] = (byte)(digest[j] ^ i);
 | 
			
		||||
                    PrepareRC4Key(mkey);
 | 
			
		||||
                    EncryptRC4(ownerKey);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                PrepareRC4Key(digest, 0, 5);
 | 
			
		||||
                EncryptRC4(userPad, ownerKey);
 | 
			
		||||
            }
 | 
			
		||||
            //#endif
 | 
			
		||||
            return ownerKey;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Computes the encryption key.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void InitEncryptionKey(byte[] documentID, byte[] userPad, byte[] ownerKey, int permissions, bool strongEncryption)
 | 
			
		||||
        {
 | 
			
		||||
            //#if !SILVERLIGHT
 | 
			
		||||
            _ownerKey = ownerKey;
 | 
			
		||||
            _encryptionKey = new byte[strongEncryption ? 16 : 5];
 | 
			
		||||
 | 
			
		||||
#if !NETFX_CORE
 | 
			
		||||
            _md5.Initialize();
 | 
			
		||||
            _md5.TransformBlock(userPad, 0, userPad.Length, userPad, 0);
 | 
			
		||||
            _md5.TransformBlock(ownerKey, 0, ownerKey.Length, ownerKey, 0);
 | 
			
		||||
 | 
			
		||||
            // Split permission into 4 bytes
 | 
			
		||||
            byte[] permission = new byte[4];
 | 
			
		||||
            permission[0] = (byte)permissions;
 | 
			
		||||
            permission[1] = (byte)(permissions >> 8);
 | 
			
		||||
            permission[2] = (byte)(permissions >> 16);
 | 
			
		||||
            permission[3] = (byte)(permissions >> 24);
 | 
			
		||||
            _md5.TransformBlock(permission, 0, 4, permission, 0);
 | 
			
		||||
            _md5.TransformBlock(documentID, 0, documentID.Length, documentID, 0);
 | 
			
		||||
            _md5.TransformFinalBlock(permission, 0, 0);
 | 
			
		||||
            byte[] digest = _md5.Hash;
 | 
			
		||||
            _md5.Initialize();
 | 
			
		||||
            // Create the hash 50 times (only for 128 bit)
 | 
			
		||||
            if (_encryptionKey.Length == 16)
 | 
			
		||||
            {
 | 
			
		||||
                for (int idx = 0; idx < 50; idx++)
 | 
			
		||||
                {
 | 
			
		||||
                    digest = _md5.ComputeHash(digest);
 | 
			
		||||
                    _md5.Initialize();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Array.Copy(digest, 0, _encryptionKey, 0, _encryptionKey.Length);
 | 
			
		||||
            //#endif
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Computes the user key.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void SetupUserKey(byte[] documentID)
 | 
			
		||||
        {
 | 
			
		||||
#if !NETFX_CORE
 | 
			
		||||
            //#if !SILVERLIGHT
 | 
			
		||||
            if (_encryptionKey.Length == 16)
 | 
			
		||||
            {
 | 
			
		||||
                _md5.TransformBlock(PasswordPadding, 0, PasswordPadding.Length, PasswordPadding, 0);
 | 
			
		||||
                _md5.TransformFinalBlock(documentID, 0, documentID.Length);
 | 
			
		||||
                byte[] digest = _md5.Hash;
 | 
			
		||||
                _md5.Initialize();
 | 
			
		||||
                Array.Copy(digest, 0, _userKey, 0, 16);
 | 
			
		||||
                for (int idx = 16; idx < 32; idx++)
 | 
			
		||||
                    _userKey[idx] = 0;
 | 
			
		||||
                //Encrypt the key
 | 
			
		||||
                for (int i = 0; i < 20; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    for (int j = 0; j < _encryptionKey.Length; j++)
 | 
			
		||||
                        digest[j] = (byte)(_encryptionKey[j] ^ i);
 | 
			
		||||
                    PrepareRC4Key(digest, 0, _encryptionKey.Length);
 | 
			
		||||
                    EncryptRC4(_userKey, 0, 16);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                PrepareRC4Key(_encryptionKey);
 | 
			
		||||
                EncryptRC4(PasswordPadding, _userKey);
 | 
			
		||||
            }
 | 
			
		||||
            //#endif
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Prepare the encryption key.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void PrepareKey()
 | 
			
		||||
        {
 | 
			
		||||
            if (_key != null && _keySize > 0) //!!!mod 2017-11-06 Added "if" because PrepareRC4Key fails if _key is null. But _key appears to be always null, so maybe PrepareKey() is obsolete.
 | 
			
		||||
            PrepareRC4Key(_key, 0, _keySize);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Prepare the encryption key.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void PrepareRC4Key(byte[] key)
 | 
			
		||||
        {
 | 
			
		||||
            PrepareRC4Key(key, 0, key.Length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Prepare the encryption key.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void PrepareRC4Key(byte[] key, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            int idx1 = 0;
 | 
			
		||||
            int idx2 = 0;
 | 
			
		||||
            for (int idx = 0; idx < 256; idx++)
 | 
			
		||||
                _state[idx] = (byte)idx;
 | 
			
		||||
            byte tmp;
 | 
			
		||||
            for (int idx = 0; idx < 256; idx++)
 | 
			
		||||
            {
 | 
			
		||||
                idx2 = (key[idx1 + offset] + _state[idx] + idx2) & 255;
 | 
			
		||||
                tmp = _state[idx];
 | 
			
		||||
                _state[idx] = _state[idx2];
 | 
			
		||||
                _state[idx2] = tmp;
 | 
			
		||||
                idx1 = (idx1 + 1) % length;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts the data.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        // ReSharper disable InconsistentNaming
 | 
			
		||||
        void EncryptRC4(byte[] data)
 | 
			
		||||
        // ReSharper restore InconsistentNaming
 | 
			
		||||
        {
 | 
			
		||||
            EncryptRC4(data, 0, data.Length, data);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts the data.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        // ReSharper disable InconsistentNaming
 | 
			
		||||
        void EncryptRC4(byte[] data, int offset, int length)
 | 
			
		||||
        // ReSharper restore InconsistentNaming
 | 
			
		||||
        {
 | 
			
		||||
            EncryptRC4(data, offset, length, data);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts the data.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void EncryptRC4(byte[] inputData, byte[] outputData)
 | 
			
		||||
        {
 | 
			
		||||
            EncryptRC4(inputData, 0, inputData.Length, outputData);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypts the data.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void EncryptRC4(byte[] inputData, int offset, int length, byte[] outputData)
 | 
			
		||||
        {
 | 
			
		||||
            length += offset;
 | 
			
		||||
            int x = 0, y = 0;
 | 
			
		||||
            byte b;
 | 
			
		||||
            for (int idx = offset; idx < length; idx++)
 | 
			
		||||
            {
 | 
			
		||||
                x = (x + 1) & 255;
 | 
			
		||||
                y = (_state[x] + y) & 255;
 | 
			
		||||
                b = _state[x];
 | 
			
		||||
                _state[x] = _state[y];
 | 
			
		||||
                _state[y] = b;
 | 
			
		||||
                outputData[idx] = (byte)(inputData[idx] ^ _state[(_state[x] + _state[y]) & 255]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Checks whether the calculated key correct.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        bool EqualsKey(byte[] value, int length)
 | 
			
		||||
        {
 | 
			
		||||
            for (int idx = 0; idx < length; idx++)
 | 
			
		||||
            {
 | 
			
		||||
                if (_userKey[idx] != value[idx])
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Set the hash key for the specified object.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal void SetHashKey(PdfObjectID id)
 | 
			
		||||
        {
 | 
			
		||||
#if !NETFX_CORE
 | 
			
		||||
            //#if !SILVERLIGHT
 | 
			
		||||
            byte[] objectId = new byte[5];
 | 
			
		||||
            _md5.Initialize();
 | 
			
		||||
            // Split the object number and generation
 | 
			
		||||
            objectId[0] = (byte)id.ObjectNumber;
 | 
			
		||||
            objectId[1] = (byte)(id.ObjectNumber >> 8);
 | 
			
		||||
            objectId[2] = (byte)(id.ObjectNumber >> 16);
 | 
			
		||||
            objectId[3] = (byte)id.GenerationNumber;
 | 
			
		||||
            objectId[4] = (byte)(id.GenerationNumber >> 8);
 | 
			
		||||
            _md5.TransformBlock(_encryptionKey, 0, _encryptionKey.Length, _encryptionKey, 0);
 | 
			
		||||
            _md5.TransformFinalBlock(objectId, 0, objectId.Length);
 | 
			
		||||
            _key = _md5.Hash;
 | 
			
		||||
            _md5.Initialize();
 | 
			
		||||
            _keySize = _encryptionKey.Length + 5;
 | 
			
		||||
            if (_keySize > 16)
 | 
			
		||||
                _keySize = 16;
 | 
			
		||||
            //#endif
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Prepares the security handler for encrypting the document.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void PrepareEncryption()
 | 
			
		||||
        {
 | 
			
		||||
            //#if !SILVERLIGHT
 | 
			
		||||
            Debug.Assert(_document._securitySettings.DocumentSecurityLevel != PdfDocumentSecurityLevel.None);
 | 
			
		||||
            int permissions = (int)Permission;
 | 
			
		||||
            bool strongEncryption = _document._securitySettings.DocumentSecurityLevel == PdfDocumentSecurityLevel.Encrypted128Bit;
 | 
			
		||||
 | 
			
		||||
            PdfInteger vValue;
 | 
			
		||||
            PdfInteger length;
 | 
			
		||||
            PdfInteger rValue;
 | 
			
		||||
 | 
			
		||||
            if (strongEncryption)
 | 
			
		||||
            {
 | 
			
		||||
                vValue = new PdfInteger(2);
 | 
			
		||||
                length = new PdfInteger(128);
 | 
			
		||||
                rValue = new PdfInteger(3);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                vValue = new PdfInteger(1);
 | 
			
		||||
                length = new PdfInteger(40);
 | 
			
		||||
                rValue = new PdfInteger(2);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (String.IsNullOrEmpty(_userPassword))
 | 
			
		||||
                _userPassword = "";
 | 
			
		||||
            // Use user password twice if no owner password provided.
 | 
			
		||||
            if (String.IsNullOrEmpty(_ownerPassword))
 | 
			
		||||
                _ownerPassword = _userPassword;
 | 
			
		||||
 | 
			
		||||
            // Correct permission bits
 | 
			
		||||
            permissions |= (int)(strongEncryption ? (uint)0xfffff0c0 : (uint)0xffffffc0);
 | 
			
		||||
            permissions &= unchecked((int)0xfffffffc);
 | 
			
		||||
 | 
			
		||||
            PdfInteger pValue = new PdfInteger(permissions);
 | 
			
		||||
 | 
			
		||||
            Debug.Assert(_ownerPassword.Length > 0, "Empty owner password.");
 | 
			
		||||
            byte[] userPad = PadPassword(_userPassword);
 | 
			
		||||
            byte[] ownerPad = PadPassword(_ownerPassword);
 | 
			
		||||
 | 
			
		||||
            _md5.Initialize();
 | 
			
		||||
            _ownerKey = ComputeOwnerKey(userPad, ownerPad, strongEncryption);
 | 
			
		||||
            byte[] documentID = PdfEncoders.RawEncoding.GetBytes(_document.Internals.FirstDocumentID);
 | 
			
		||||
            InitWithUserPassword(documentID, _userPassword, _ownerKey, permissions, strongEncryption);
 | 
			
		||||
 | 
			
		||||
            PdfString oValue = new PdfString(PdfEncoders.RawEncoding.GetString(_ownerKey, 0, _ownerKey.Length));
 | 
			
		||||
            PdfString uValue = new PdfString(PdfEncoders.RawEncoding.GetString(_userKey, 0, _userKey.Length));
 | 
			
		||||
 | 
			
		||||
            Elements[Keys.Filter] = new PdfName("/Standard");
 | 
			
		||||
            Elements[Keys.V] = vValue;
 | 
			
		||||
            Elements[Keys.Length] = length;
 | 
			
		||||
            Elements[Keys.R] = rValue;
 | 
			
		||||
            Elements[Keys.O] = oValue;
 | 
			
		||||
            Elements[Keys.U] = uValue;
 | 
			
		||||
            Elements[Keys.P] = pValue;
 | 
			
		||||
            //#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The global encryption key.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        byte[] _encryptionKey;
 | 
			
		||||
 | 
			
		||||
#if !SILVERLIGHT && !UWP
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The message digest algorithm MD5.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        readonly MD5 _md5 = new MD5CryptoServiceProvider();
 | 
			
		||||
#if DEBUG_
 | 
			
		||||
        readonly MD5Managed _md5M = new MD5Managed();
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
        readonly MD5Managed _md5 = new MD5Managed();
 | 
			
		||||
#endif
 | 
			
		||||
#if NETFX_CORE
 | 
			
		||||
        // readonly MD5Managed _md5 = new MD5Managed();
 | 
			
		||||
#endif
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Bytes used for RC4 encryption.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        readonly byte[] _state = new byte[256];
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The encryption key for the owner.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        byte[] _ownerKey = new byte[32];
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The encryption key for the user.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        readonly byte[] _userKey = new byte[32];
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The encryption key for a particular object/generation.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        byte[] _key;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The encryption key length for a particular object/generation.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        int _keySize;
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        internal override void WriteObject(PdfWriter writer)
 | 
			
		||||
        {
 | 
			
		||||
            // Don't encrypt myself.
 | 
			
		||||
            PdfStandardSecurityHandler securityHandler = writer.SecurityHandler;
 | 
			
		||||
            writer.SecurityHandler = null;
 | 
			
		||||
            base.WriteObject(writer);
 | 
			
		||||
            writer.SecurityHandler = securityHandler;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Keys
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Predefined keys of this dictionary.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal sealed new class Keys : PdfSecurityHandler.Keys
 | 
			
		||||
        {
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Required) A number specifying which revision of the standard security handler
 | 
			
		||||
            /// should be used to interpret this dictionary:
 | 
			
		||||
            /// <20> 2 if the document is encrypted with a V value less than 2 and does not have any of
 | 
			
		||||
            ///   the access permissions set (by means of the P entry, below) that are designated 
 | 
			
		||||
            ///   "Revision 3 or greater".
 | 
			
		||||
            /// <20> 3 if the document is encrypted with a V value of 2 or 3, or has any "Revision 3 or 
 | 
			
		||||
            ///   greater" access permissions set.
 | 
			
		||||
            /// <20> 4 if the document is encrypted with a V value of 4
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo(KeyType.Integer | KeyType.Required)]
 | 
			
		||||
            public const string R = "/R";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Required) A 32-byte string, based on both the owner and user passwords, that is
 | 
			
		||||
            /// used in computing the encryption key and in determining whether a valid owner
 | 
			
		||||
            /// password was entered.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo(KeyType.String | KeyType.Required)]
 | 
			
		||||
            public const string O = "/O";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Required) A 32-byte string, based on the user password, that is used in determining
 | 
			
		||||
            /// whether to prompt the user for a password and, if so, whether a valid user or owner 
 | 
			
		||||
            /// password was entered.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo(KeyType.String | KeyType.Required)]
 | 
			
		||||
            public const string U = "/U";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Required) A set of flags specifying which operations are permitted when the document
 | 
			
		||||
            /// is opened with user access.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo(KeyType.Integer | KeyType.Required)]
 | 
			
		||||
            public const string P = "/P";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// (Optional; meaningful only when the value of V is 4; PDF 1.5) Indicates whether
 | 
			
		||||
            /// the document-level metadata stream is to be encrypted. Applications should respect this value.
 | 
			
		||||
            /// Default value: true.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            [KeyInfo(KeyType.Boolean | KeyType.Optional)]
 | 
			
		||||
            public const string EncryptMetadata = "/EncryptMetadata";
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Gets the KeysMeta for these keys.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            public static DictionaryMeta Meta
 | 
			
		||||
            {
 | 
			
		||||
                get { return _meta ?? (_meta = CreateMeta(typeof(Keys))); }
 | 
			
		||||
            }
 | 
			
		||||
            static DictionaryMeta _meta;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets the KeysMeta of this dictionary type.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal override DictionaryMeta Meta
 | 
			
		||||
        {
 | 
			
		||||
            get { return Keys.Meta; }
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								PrintPDF/PdfSharp/Pdf.Security/enums/PdfDocumentSecurity.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								PrintPDF/PdfSharp/Pdf.Security/enums/PdfDocumentSecurity.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
#region PDFsharp - A .NET library for processing PDF
 | 
			
		||||
//
 | 
			
		||||
// Authors:
 | 
			
		||||
//   Stefan Lange
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
 | 
			
		||||
//
 | 
			
		||||
// http://www.pdfsharp.com
 | 
			
		||||
// http://sourceforge.net/projects/pdfsharp
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
// copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
// to deal in the Software without restriction, including without limitation
 | 
			
		||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
// and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
// Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included
 | 
			
		||||
// in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 | 
			
		||||
// DEALINGS IN THE SOFTWARE.
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.Pdf.Security
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Specifies the security level of the PDF document.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public enum PdfDocumentSecurityLevel
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Document is not protected.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        None,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Document is protected with 40-bit security. This option is for compatibility with 
 | 
			
		||||
        /// Acrobat 3 and 4 only. Use Encrypted128Bit whenever possible.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Encrypted40Bit,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Document is protected with 128-bit security.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Encrypted128Bit,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,92 @@
 | 
			
		||||
#region PDFsharp - A .NET library for processing PDF
 | 
			
		||||
//
 | 
			
		||||
// Authors:
 | 
			
		||||
//   Stefan Lange
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
 | 
			
		||||
//
 | 
			
		||||
// http://www.pdfsharp.com
 | 
			
		||||
// http://sourceforge.net/projects/pdfsharp
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
// copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
// to deal in the Software without restriction, including without limitation
 | 
			
		||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
// and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
// Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included
 | 
			
		||||
// in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 | 
			
		||||
// DEALINGS IN THE SOFTWARE.
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.Pdf.Security
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Specifies which operations are permitted when the document is opened with user access.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Flags]
 | 
			
		||||
    internal enum PdfUserAccessPermission
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permits everything. This is the default value.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        PermitAll = -3, // = 0xFFFFFFFC,
 | 
			
		||||
 | 
			
		||||
        // Bit 1<>2 Reserved; must be 0.
 | 
			
		||||
 | 
			
		||||
        // Bit 3 (Revision 2) Print the document.
 | 
			
		||||
        // (Revision 3 or greater) Print the document (possibly not at the highest
 | 
			
		||||
        // quality level, depending on whether bit 12 is also set).
 | 
			
		||||
        PermitPrint = 0x00000004,  //1 << (3 - 1),
 | 
			
		||||
 | 
			
		||||
        // Bit 4 Modify the contents of the document by operations other than
 | 
			
		||||
        // those controlled by bits 6, 9, and 11.
 | 
			
		||||
        PermitModifyDocument = 0x00000008,  //1 << (4 - 1),
 | 
			
		||||
 | 
			
		||||
        // Bit 5 (Revision 2) Copy or otherwise extract text and graphics from the
 | 
			
		||||
        // document, including extracting text and graphics (in support of accessibility
 | 
			
		||||
        // to users with disabilities or for other purposes).
 | 
			
		||||
        // (Revision 3 or greater) Copy or otherwise extract text and graphics
 | 
			
		||||
        // from the document by operations other than that controlled by bit 10.
 | 
			
		||||
        PermitExtractContent = 0x00000010,  //1 << (5 - 1),
 | 
			
		||||
 | 
			
		||||
        // Bit 6 Add or modify text annotations, fill in interactive form fields, and,
 | 
			
		||||
        // if bit 4 is also set, create or modify interactive form fields (including
 | 
			
		||||
        // signature fields).
 | 
			
		||||
        PermitAnnotations = 0x00000020,  //1 << (6 - 1),
 | 
			
		||||
 | 
			
		||||
        // Bit 7<>8 Reserved; must be 1.
 | 
			
		||||
 | 
			
		||||
        // 9 (Revision 3 or greater) Fill in existing interactive form fields (including
 | 
			
		||||
        // signature fields), even if bit 6 is clear.
 | 
			
		||||
        PermitFormsFill = 0x00000100,  //1 << (9 - 1),
 | 
			
		||||
 | 
			
		||||
        // Bit 10 (Revision 3 or greater) Extract text and graphics (in support of accessibility
 | 
			
		||||
        // to users with disabilities or for other purposes).
 | 
			
		||||
        PermitAccessibilityExtractContent = 0x00000200,  //1 << (10 - 1),
 | 
			
		||||
 | 
			
		||||
        // Bit 11 (Revision 3 or greater) Assemble the document (insert, rotate, or delete
 | 
			
		||||
        // pages and create bookmarks or thumbnail images), even if bit 4
 | 
			
		||||
        // is clear.
 | 
			
		||||
        PermitAssembleDocument = 0x00000400,  //1 << (11 - 1),
 | 
			
		||||
 | 
			
		||||
        // Bit 12 (Revision 3 or greater) Print the document to a representation from
 | 
			
		||||
        // which a faithful digital copy of the PDF content could be generated.
 | 
			
		||||
        // When this bit is clear (and bit 3 is set), printing is limited to a lowlevel
 | 
			
		||||
        // representation of the appearance, possibly of degraded quality.
 | 
			
		||||
        // (See implementation note 24 in Appendix H.)
 | 
			
		||||
        PermitFullQualityPrint = 0x00000800,  //1 << (12 - 1),
 | 
			
		||||
 | 
			
		||||
        //Bit 13<31>32 (Revision 3 or greater) Reserved; must be 1.
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user