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