/// <summary>
        /// Decode a Gss_Wrap token from security buffers
        /// </summary>
        /// <param name="context">The context of decoding</param>
        /// <param name="securityBuffers">Security buffers</param>
        /// <returns>The decoded Gss_Wrap token.</returns>
        internal static KerberosPdu GssUnWrapEx(KerberosContext context, SecurityBuffer[] securityBuffers)
        {
            KerberosPdu   pdu = null;
            EncryptionKey key = context.ContextKey;

            switch ((EncryptionType)key.keytype.Value)
            {
            case EncryptionType.AES128_CTS_HMAC_SHA1_96:
            case EncryptionType.AES256_CTS_HMAC_SHA1_96:
                var token4121Pdu = new Token4121(context);
                token4121Pdu.FromSecurityBuffers(securityBuffers);
                pdu = token4121Pdu;
                break;

            case EncryptionType.DES_CBC_CRC:
            case EncryptionType.DES_CBC_MD5:
            case EncryptionType.RC4_HMAC:
            case EncryptionType.RC4_HMAC_EXP:
                var token1964or4757Pdu = new Token1964_4757(context);
                token1964or4757Pdu.FromSecurityBuffers(securityBuffers);
                pdu = token1964or4757Pdu;
                break;

            default:
                throw new NotSupportedException("The Encryption Type can only be AES128_CTS_HMAC_SHA1_96, "
                                                + "AES256_CTS_HMAC_SHA1_96, DES_CBC_CRC, DES_CBC_MD5, RC4_HMAC or RC4_HMAC_EXP.");
            }

            return(pdu);
        }
        internal static bool GssVerifyMicEx(KerberosContext context, SecurityBuffer[] securityBuffers, out KerberosPdu pdu)
        {
            pdu = null;
            bool          isVerified = true;
            EncryptionKey key        = context.ContextKey;

            switch ((EncryptionType)key.keytype.Value)
            {
            case EncryptionType.AES128_CTS_HMAC_SHA1_96:
            case EncryptionType.AES256_CTS_HMAC_SHA1_96:
                var micPdu4121 = new Token4121(context);
                try
                {
                    micPdu4121.FromSecurityBuffers(securityBuffers);
                }
                catch (FormatException)
                {
                    isVerified = false;
                }
                pdu = micPdu4121;
                break;

            case EncryptionType.DES_CBC_CRC:
            case EncryptionType.DES_CBC_MD5:
            case EncryptionType.RC4_HMAC:
            case EncryptionType.RC4_HMAC_EXP:
                var micPdu1964_4757 = new Token1964_4757(context);
                try
                {
                    micPdu1964_4757.FromSecurityBuffers(securityBuffers);
                }
                catch (FormatException)
                {
                    isVerified = false;
                }
                pdu = micPdu1964_4757;
                break;

            default:
                throw new NotSupportedException("The Encryption Type can only be AES128_CTS_HMAC_SHA1_96, "
                                                + "AES256_CTS_HMAC_SHA1_96, DES_CBC_CRC, DES_CBC_MD5, RC4_HMAC or RC4_HMAC_EXP.");
            }

            return(isVerified);
        }
        /// <summary>
        /// This takes the given byte array, decrypts it, and returns
        /// the original, unencrypted byte array.
        /// </summary>
        /// <param name="kileRole">Represents client or server</param>
        /// <param name="securityBuffers">The security buffers to decrypt.</param>
        /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception>
        internal static bool Decrypt(KileRole kileRole, params SecurityBuffer[] securityBuffers)
        {
            KilePdu pdu = kileRole.GssUnWrapEx(securityBuffers);

            byte[] decryptedMessage = null;

            if (pdu.GetType() == typeof(Token4121))
            {
                decryptedMessage = ((Token4121)pdu).Data;
            }
            else if (pdu.GetType() == typeof(Token1964_4757))
            {
                Token1964_4757 tokenData = (Token1964_4757)pdu;
                decryptedMessage = tokenData.Data;
                SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Padding, tokenData.paddingData);
            }
            // else do nothing

            return(true);
        }
        /// <summary>
        /// Decrypt a request or response
        /// </summary>
        /// <param name="token">A token containing encrypted data.</param>
        /// <param name="sentFromClient">True if the token is a request, false is a response</param>
        /// <returns>Plain-text data.</returns>
        private byte[] Decrypt(byte[] token, bool sentFromClient)
        {
            KileContext context = sentFromClient ? (KileContext)kileDecoder.serverContext : (KileContext)kileDecoder.clientContext;
            KilePdu     pdu     = KileRole.GssUnWrap(context, token);

            Token4121 token4121Pdu = pdu as Token4121;

            if (token4121Pdu != null)
            {
                return(token4121Pdu.Data);
            }

            Token1964_4757 token1964or4757Pdu = pdu as Token1964_4757;

            if (token1964or4757Pdu != null)
            {
                return(token1964or4757Pdu.Data);
            }

            throw new InvalidOperationException("Token type is not supported.");
        }
        private Token1964_4757 WrapToken1964_4757(GssTokenType tokenType, byte[] message, bool isEncrypted, SGN_ALG signAlgorithm)
        {
            var token = new Token1964_4757(Context);
            TokenHeader1964_4757 tokenHeader = new TokenHeader1964_4757();

            tokenHeader.filler  = KerberosConstValue.TOKEN_FILLER_2_BYTE;
            tokenHeader.sng_alg = signAlgorithm;

            switch (tokenType)
            {
            case GssTokenType.Wrap4757:
            {
                tokenHeader.tok_id   = TOK_ID.Wrap1964_4757;
                tokenHeader.seal_alg = isEncrypted ? SEAL_ALG.RC4 : SEAL_ALG.NONE;
            }
            break;

            case GssTokenType.Wrap1964:
            {
                tokenHeader.tok_id   = TOK_ID.Wrap1964_4757;
                tokenHeader.seal_alg = isEncrypted ? SEAL_ALG.DES : SEAL_ALG.NONE;
            }
            break;

            case GssTokenType.Mic1964_4757:
            {
                tokenHeader.tok_id   = TOK_ID.Mic1964_4757;
                tokenHeader.seal_alg = SEAL_ALG.NONE;
            }
            break;
            }
            token.TokenHeader = tokenHeader;
            token.Data        = message;

            return(token);
        }