/// <summary>
        /// Create a Gss_Wrap token. Then use KilePdu.ToBytes() to get the byte array.
        /// </summary>
        /// <param name="isEncrypted">If encrypt the message.</param>
        /// <param name="signAlgorithm">Specify the checksum type.
        /// This is only used for encryption types DES and RC4.</param>
        /// <param name="message">The message to be wrapped. This argument can be null.</param>
        /// <returns>The created Gss_Wrap token.</returns>
        /// <exception cref="System.NotSupportedException">Thrown when the encryption type is not supported.</exception>
        public KerberosPdu GssWrap(bool isEncrypted, SGN_ALG signAlgorithm, byte[] message)
        {
            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:
                pdu = GssWrap4121(isEncrypted, message, Context.IsInitiator);
                break;

            case EncryptionType.DES_CBC_CRC:
            case EncryptionType.DES_CBC_MD5:
                pdu = GssWrap1964(isEncrypted, signAlgorithm, message);
                break;

            case EncryptionType.RC4_HMAC:
            case EncryptionType.RC4_HMAC_EXP:
                pdu = GssWrap4757(isEncrypted, signAlgorithm, message);
                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);
        }
        /// <summary>
        /// Encrypts Message. User decides what SecBuffers are used.
        /// </summary>
        /// <param name="kileRole">Represents client or server</param>
        /// <param name="securityBuffers">The security buffers to encrypt.</param>
        /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception>
        internal static void Encrypt(KileRole kileRole, params SecurityBuffer[] securityBuffers)
        {
            byte[] message = SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Data);
            byte[] token   = SspiUtility.ConcatenateSecurityBuffers(securityBuffers, SecurityBufferType.Token);

            if (token.Length == 0)
            {
                throw new ArgumentException("Token buffer is not valid.");
            }

            SGN_ALG sgnAlg = GetSgnAlg(kileRole);
            KilePdu pdu    = kileRole.GssWrap(true, sgnAlg, message);

            byte[] cipherData = null;

            if (pdu.GetType() == typeof(Token4121))
            {
                cipherData = pdu.ToBytes();
            }
            else
            {
                byte[] allData     = pdu.ToBytes();
                byte[] paddingData = ((Token1964_4757)pdu).paddingData;
                cipherData = ArrayUtility.SubArray(allData, 0, allData.Length - paddingData.Length);
                SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Padding, paddingData);
            }
            SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Data,
                                              ArrayUtility.SubArray(cipherData, cipherData.Length - message.Length));
            SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token,
                                              ArrayUtility.SubArray(cipherData, 0, cipherData.Length - message.Length));
        }
        /// <summary>
        /// This takes the given SecurityBuffer array, signs data part, and updates signature into token part
        /// </summary>
        /// <param name="kileRole">Represents client or server</param>
        /// <param name="securityBuffers">Data to sign and token to update.</param>
        /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception>
        internal static void Sign(KileRole kileRole, params SecurityBuffer[] securityBuffers)
        {
            byte[] token = SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Token);

            if (token.Length == 0)
            {
                throw new ArgumentException("No token can be updated for signature.");
            }
            byte[]  message = GetToBeSignedDataFromSecurityBuffers(securityBuffers);
            SGN_ALG sgnAlg  = GetSgnAlg(kileRole);
            KilePdu pdu     = kileRole.GssGetMic(sgnAlg, message);

            byte[] signature = pdu.ToBytes();

            SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token, signature);
        }
        /// <summary>
        /// Get SGN_ALG for encryption and sign.
        /// </summary>
        /// <returns>The SGN_ALG got from context.</returns>
        /// <exception cref="System.FormatException">Thrown when the key is not valid.</exception>
        internal static SGN_ALG GetSgnAlg(EncryptionKey contextKey)
        {
            if (contextKey == null || contextKey.keytype == null || contextKey.keyvalue == null || contextKey.keyvalue.Value == null)
            {
                throw new FormatException("Initialization is not complete successfully!");
            }

            SGN_ALG        sgnAlg = SGN_ALG.HMAC;
            EncryptionType type   = (EncryptionType)contextKey.keytype.Value;

            if (type == EncryptionType.DES_CBC_MD5 || type == EncryptionType.DES_CBC_CRC)
            {
                sgnAlg = SGN_ALG.DES_MAC_MD5;
            }

            return(sgnAlg);
        }
        /// <summary>
        /// Get SGN_ALG for encryption and sign.
        /// </summary>
        /// <returns>The SGN_ALG got from context.</returns>
        /// <exception cref="System.FormatException">Thrown when the key is not valid.</exception>
        private static SGN_ALG GetSgnAlg(KileRole kileRole)
        {
            EncryptionKey key = kileRole.Context.ContextKey;

            if (key == null || key.keytype == null || key.keyvalue == null || key.keyvalue.Value == null)
            {
                throw new FormatException("Initialization is not complete successfully!");
            }

            SGN_ALG        sgnAlg = SGN_ALG.HMAC;
            EncryptionType type   = (EncryptionType)key.keytype.Value;

            if (type == EncryptionType.DES_CBC_MD5 || type == EncryptionType.DES_CBC_CRC)
            {
                sgnAlg = SGN_ALG.DES_MAC_MD5;
            }

            return(sgnAlg);
        }
 public KilePdu GssWrap(KileConnection kileConnection, bool isEncrypted, SGN_ALG signAlgorithm, byte[] message)
 {
     context = GetServerContextByKileConnection(kileConnection);
     return GssWrap(isEncrypted, signAlgorithm, message);
 }
 public KilePdu GssGetMic(KileConnection kileConnection, SGN_ALG signAlgorithm, byte[] message)
 {
     context = GetServerContextByKileConnection(kileConnection);
     return GssGetMic(signAlgorithm, message);
 }
 /// <summary>
 /// Create a Gss_GetMic token. Then use KilePdu.ToBytes() to get the byte array.
 /// </summary>
 /// <param name="kileConnection">Maintain a connection with a target client</param>
 /// <param name="signAlgorithm">Specify the checksum type.
 /// This is only used for encryption types DES and RC4.</param>
 /// <param name="message">The message to be computed signature. This argument can be null.</param>
 /// <returns>The created Gss_GetMic token, NotSupportedException.</returns>
 /// <exception cref="System.NotSupportedException">Thrown when the encryption is not supported.</exception>
 public KilePdu GssGetMic(KileConnection kileConnection, SGN_ALG signAlgorithm, byte[] message)
 {
     context = GetServerContextByKileConnection(kileConnection);
     return(GssGetMic(signAlgorithm, message));
 }
 /// <summary>
 /// Create a Gss_Wrap token. Then use KilePdu.ToBytes() to get the byte array.
 /// </summary>
 /// <param name="kileConnection">Maintain a connection with a target client</param>
 /// <param name="isEncrypted">If encrypt the message.</param>
 /// <param name="signAlgorithm">Specify the checksum type.
 /// This is only used for encryption types DES and RC4.</param>
 /// <param name="message">The message to be wrapped. This argument can be null.</param>
 /// <returns>The created Gss_Wrap token.</returns>
 /// <exception cref="System.NotSupportedException">Thrown when the encryption is not supported.</exception>
 public KilePdu GssWrap(KileConnection kileConnection, bool isEncrypted, SGN_ALG signAlgorithm, byte[] message)
 {
     context = GetServerContextByKileConnection(kileConnection);
     return(GssWrap(isEncrypted, signAlgorithm, message));
 }
        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);
        }
 /// <summary>
 /// Create a Gss_Wrap [RFC4757] token.
 /// </summary>
 /// <param name="isEncrypted">If encrypt the message.</param>
 /// <param name="signAlgorithm">Specify the checksum type.</param>
 /// <param name="message">The message to be wrapped. This argument can be null.</param>
 /// <returns>The created Gss_Wrap token.</returns>
 private Token1964_4757 GssWrap4757(bool isEncrypted, SGN_ALG signAlgorithm, byte[] message)
 {
     return(WrapToken1964_4757(GssTokenType.Wrap4757, message, isEncrypted, signAlgorithm));
 }
 /// <summary>
 /// Create a Gss_GetMic [RFC1964] token.
 /// </summary>
 /// <param name="signAlgorithm">Specify the checksum type.</param>
 /// <param name="message">The message to be wrapped. This argument can be null.</param>
 /// <returns>The created Gss_GetMic token.</returns>
 private Token1964_4757 GssGetMic1964_4757(SGN_ALG signAlgorithm, byte[] message)
 {
     return(WrapToken1964_4757(GssTokenType.Mic1964_4757, message, false, signAlgorithm));
 }