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