Exemplo n.º 1
0
        public bool TryGetCryptHandler(out CryptHandler cryptHandler)
        {
            cryptHandler = null;

            if (EncryptionAlgorithmCode != EncryptionAlgorithmCode.SecurityHandlerInDocument &&
                EncryptionAlgorithmCode != EncryptionAlgorithmCode.SecurityHandlerInDocument256)
            {
                return(false);
            }

            if (!Dictionary.TryGet(NameToken.Cf, out DictionaryToken cryptFilterDictionary))
            {
                return(false);
            }

            var namedFilters = cryptFilterDictionary;

            var streamFilterName = Dictionary.TryGet(NameToken.StmF, out NameToken streamFilterToken) ? streamFilterToken : NameToken.Identity;
            var stringFilterName = Dictionary.TryGet(NameToken.StrF, out NameToken stringFilterToken) ? stringFilterToken : NameToken.Identity;

            if (streamFilterName != NameToken.Identity && !namedFilters.TryGet(streamFilterName, out _))
            {
                throw new PdfDocumentEncryptedException($"Stream filter {streamFilterName} not found in crypt dictionary: {cryptFilterDictionary}.");
            }

            if (stringFilterName != NameToken.Identity && !namedFilters.TryGet(stringFilterName, out _))
            {
                throw new PdfDocumentEncryptedException($"String filter {stringFilterName} not found in crypt dictionary: {cryptFilterDictionary}.");
            }

            cryptHandler = new CryptHandler(namedFilters, streamFilterName, stringFilterName);

            return(true);
        }
Exemplo n.º 2
0
        public EncryptionHandler(EncryptionDictionary encryptionDictionary, TrailerDictionary trailerDictionary, IReadOnlyList <string> passwords)
        {
            this.encryptionDictionary = encryptionDictionary;

            passwords = passwords ?? new[] { string.Empty };

            if (!passwords.Contains(string.Empty))
            {
                passwords = new List <string>(passwords)
                {
                    string.Empty
                };
            }

            byte[] documentIdBytes;

            if (trailerDictionary.Identifier != null && trailerDictionary.Identifier.Count == 2)
            {
                var token = trailerDictionary.Identifier[0];

                switch (token)
                {
                case HexToken hex:
                    documentIdBytes = hex.Bytes.ToArray();
                    break;

                default:
                    documentIdBytes = OtherEncodings.StringAsLatin1Bytes(token.Data);
                    break;
                }
            }
            else
            {
                documentIdBytes = EmptyArray <byte> .Instance;
            }

            if (encryptionDictionary == null)
            {
                return;
            }

            useAes = false;

            if (encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.SecurityHandlerInDocument ||
                encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.SecurityHandlerInDocument256)
            {
                if (!encryptionDictionary.TryGetCryptHandler(out var cryptHandlerLocal))
                {
                    throw new PdfDocumentEncryptedException("Document encrypted with security handler in document but no crypt dictionary found.", encryptionDictionary);
                }

                cryptHandler = cryptHandlerLocal;

                useAes = cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV2 ||
                         cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV3;
            }

            var charset = OtherEncodings.Iso88591;

            if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
            {
                // ReSharper disable once RedundantAssignment
                charset = Encoding.UTF8;
            }

            var length = encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.Rc4OrAes40BitKey
                ? 5
                : encryptionDictionary.KeyLength.GetValueOrDefault() / 8;

            var foundPassword = false;

            foreach (var password in passwords)
            {
                var passwordBytes = charset.GetBytes(password);

                var    isUserPassword = false;
                byte[] decryptionPasswordBytes;

                if (IsOwnerPassword(passwordBytes, encryptionDictionary, length, documentIdBytes, out var userPassBytes))
                {
                    if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
                    {
                        decryptionPasswordBytes = passwordBytes;
                    }
                    else
                    {
                        decryptionPasswordBytes = userPassBytes;
                    }
                }
                else if (IsUserPassword(passwordBytes, encryptionDictionary, length, documentIdBytes))
                {
                    decryptionPasswordBytes = passwordBytes;
                    isUserPassword          = true;
                }
                else
                {
                    continue;
                }

                encryptionKey = CalculateEncryptionKey(decryptionPasswordBytes, encryptionDictionary,
                                                       length,
                                                       documentIdBytes,
                                                       isUserPassword);

                foundPassword = true;

                break;
            }

            if (!foundPassword)
            {
                throw new PdfDocumentEncryptedException("The document was encrypted and none of the provided passwords were the user or owner password.",
                                                        encryptionDictionary);
            }
        }
Exemplo n.º 3
0
        public EncryptionHandler(EncryptionDictionary encryptionDictionary, TrailerDictionary trailerDictionary, string password)
        {
            this.encryptionDictionary = encryptionDictionary;

            var documentIdBytes = trailerDictionary.Identifier != null && trailerDictionary.Identifier.Count == 2 ?
                                  OtherEncodings.StringAsLatin1Bytes(trailerDictionary.Identifier[0])
                : EmptyArray <byte> .Instance;

            password = password ?? string.Empty;

            if (encryptionDictionary == null)
            {
                return;
            }

            useAes = false;

            if (encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.SecurityHandlerInDocument ||
                encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.SecurityHandlerInDocument256)
            {
                if (!encryptionDictionary.TryGetCryptHandler(out var cryptHandlerLocal))
                {
                    throw new PdfDocumentEncryptedException("Document encrypted with security handler in document but no crypt dictionary found.", encryptionDictionary);
                }

                cryptHandler = cryptHandlerLocal;

                useAes = cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV2 ||
                         cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV3;
            }

            var charset = OtherEncodings.Iso88591;

            if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
            {
                // ReSharper disable once RedundantAssignment
                charset = Encoding.UTF8;
            }

            var passwordBytes = charset.GetBytes(password);

            byte[] decryptionPasswordBytes;

            var length = encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.Rc4OrAes40BitKey
                ? 5
                : encryptionDictionary.KeyLength.GetValueOrDefault() / 8;

            var isUserPassword = false;

            if (IsOwnerPassword(passwordBytes, encryptionDictionary, length, documentIdBytes, out var userPassBytes))
            {
                if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
                {
                    decryptionPasswordBytes = passwordBytes;
                }
                else
                {
                    decryptionPasswordBytes = userPassBytes;
                }
            }
            else if (IsUserPassword(passwordBytes, encryptionDictionary, length, documentIdBytes))
            {
                decryptionPasswordBytes = passwordBytes;
                isUserPassword          = true;
            }
            else
            {
                throw new PdfDocumentEncryptedException("The document was encrypted and the provided password was neither the user or owner password.", encryptionDictionary);
            }

            encryptionKey = CalculateEncryptionKey(decryptionPasswordBytes, encryptionDictionary,
                                                   length,
                                                   documentIdBytes,
                                                   isUserPassword);
        }