/// <summary> /// Prepares the security handler for encrypting the document. /// </summary> public void PrepareEncryption() { //#if !SILVERLIGHT Debug.Assert(_document._securitySettings.DocumentSecurityLevel != PdfDocumentSecurityLevel.None); var permissions = (uint)Permission; bool strongEncryption; if (_document._securitySettings.DocumentSecurityLevel == PdfDocumentSecurityLevel.Encrypted128BitAes) { strongEncryption = true; Elements[Keys.V] = new PdfInteger(4); Elements[Keys.R] = new PdfInteger(4); CryptFilterDictionary aesCryptFilter = new CryptFilterDictionary(); aesCryptFilter.CFM = CFM.AESV2; aesCryptFilter.Length = 16; PdfDictionary cryptFilters = new PdfDictionary(); cryptFilters.Elements["/StdCF"] = aesCryptFilter; Elements[Keys.CF] = cryptFilters; Elements[Keys.StmF] = new PdfName("/StdCF"); Elements[Keys.StrF] = new PdfName("/StdCF"); } else if (_document._securitySettings.DocumentSecurityLevel == PdfDocumentSecurityLevel.Encrypted128Bit) { strongEncryption = true; Elements[Keys.V] = new PdfInteger(2); Elements[Keys.Length] = new PdfInteger(128); Elements[Keys.R] = new PdfInteger(3); } else { strongEncryption = false; Elements[Keys.V] = new PdfInteger(1); Elements[Keys.Length] = new PdfInteger(40); Elements[Keys.R] = 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 |= strongEncryption ? 0xfffff0c0 : 0xffffffc0; permissions &= 0xfffffffc; var pValue = new PdfUInteger(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.O] = oValue; Elements[Keys.U] = uValue; Elements[Keys.P] = pValue; //#endif }
/// <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 <= 4)) { 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)); uint pValue = Elements.GetUInteger(Keys.P); int rValue = Elements.GetInteger(Keys.R); if (inputPassword == null) { inputPassword = ""; } bool strongEncryption; int keyLength; switch (rValue) { case 2: strongEncryption = false; keyLength = 5; break; case 3: strongEncryption = true; keyLength = Elements.GetInteger(Keys.Length) / 8; break; case 4: CryptFilterDictionary cryptFilter = new CryptFilterDictionary(Elements.GetDictionary(Keys.CF).Elements.GetDictionary("/StdCF")); if (cryptFilter.CFM != CFM.V2 && cryptFilter.CFM != CFM.AESV2 && cryptFilter.AuthEvent != AuthEvent.DocOpen) { throw new PdfReaderException(PSSR.UnsupportedCryptFilter); } strongEncryption = true; keyLength = cryptFilter.Length; if (cryptFilter.CFM == CFM.AESV2) { _document.SecuritySettings.DocumentSecurityLevel = PdfDocumentSecurityLevel.Encrypted128BitAes; } break; default: throw new PdfReaderException(PSSR.UnsupportedRevisionNumber); } // 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); }