/// <summary>
        /// initial netlogon signature token when AES is negotiated
        /// </summary>
        /// <param name="sequenceNumber">sequence number</param>
        /// <param name="sessionKey">session key</param>
        /// <param name="requestConfidentiality">confidentiality is required or not</param>
        /// <param name="isClientSideOutbound">Is client side outbound message.</param>
        /// <param name="securityBuffers">
        /// Security buffers, contains input plain-text; output cipher-text and signature.
        /// </param>
        private static void InitialNetlogonSignatureTokenWhenAesIsNegotiated(
            ref ulong sequenceNumber,
            byte[] sessionKey,
            bool requestConfidentiality,
            bool isClientSideOutbound,
            SecurityBuffer[] securityBuffers)
        {
            byte[] plainText;
            byte[] cipherText;
            byte[] token;
            NL_AUTH_SHA2_SIGNATURE nlAuthSha2Sign = new NL_AUTH_SHA2_SIGNATURE();

            //The SignatureAlgorithm first byte MUST be set to 0x13,
            //and the second byte MUST be set to 0x00.
            nlAuthSha2Sign.SignatureAlgorithm =
                NL_AUTH_SHA2_SIGNATURE_SignatureAlgorithm_Values.HMACSHA256;

            if (requestConfidentiality)
            {
                //If the Confidentiality option (section 3.3.1) is
                //requested from the application, then the SealAlgorithm
                //first byte MUST be set to 0x1A, the second byte MUST
                //be set to 0x00, and the Confounder MUST be filled with
                //cryptographically random data.
                nlAuthSha2Sign.SealAlgorithm =
                    NL_AUTH_SHA2_SIGNATURE_SealAlgorithm_Values.AES128;
                nlAuthSha2Sign.Confounder = GenerateNonce(NL_AUTH_SIGNATURE_CONFOUNDER_LENGTH);
            }
            else
            {
                //If the Confidentiality option (section 3.3.1) is not
                //requested, then the SealAlgorithm MUST be filled with
                //two bytes of 0xff, and the Confounder is not included in the token.
                nlAuthSha2Sign.SealAlgorithm =
                    NL_AUTH_SHA2_SIGNATURE_SealAlgorithm_Values.NotEncrypted;
                nlAuthSha2Sign.Confounder = null;
            }

            //The Pad MUST be filled with 0xff bytes.
            nlAuthSha2Sign.Pad = NL_AUTH_SHA2_SIGNATURE_Pad_Values.V1;

            //The Flags MUST be filled with 0x00 bytes.
            nlAuthSha2Sign.Flags = Flags_Values.V1;

            //The SequenceNumber MUST be computed using the following algorithm.
            nlAuthSha2Sign.SequenceNumber = ComputeCopySequenceNumber(sequenceNumber, isClientSideOutbound);

            //The ClientSequenceNumber MUST be incremented by 1.
            sequenceNumber += 1;

            //Compute signature
            plainText = ConcatenateSecurityBuffersForChecksum(securityBuffers);
            nlAuthSha2Sign.Checksum = ComputeSignatureWhenAesIsNegotiated(
                nlAuthSha2Sign,
                sessionKey,
                requestConfidentiality,
                plainText);

            //If the Confidentiality option is requested, the data and the Confounder
            //field MUST be encrypted. If AES is negotiated then the server MUST use
            //the AES-128 algorithm using the SessionKey with an initialization
            //vector constructed by concatenating the sequence number with
            //itself twice (thus getting 16 bytes of data)
            if (requestConfidentiality)
            {
                byte[] aesEncryptionKey = ComputeEncryptionKeyWhenAesIsNegotiated(sessionKey);

                using (BCryptAlgorithm aes = new BCryptAlgorithm("AES"))
                {
                    aes.Mode = BCryptCipherMode.CFB;
                    aes.Key = aesEncryptionKey;
                    aes.IV = ArrayUtility.ConcatenateArrays(
                        nlAuthSha2Sign.SequenceNumber,
                        nlAuthSha2Sign.SequenceNumber);
                    nlAuthSha2Sign.Confounder = aes.Encrypt(nlAuthSha2Sign.Confounder);

                    plainText = SspiUtility.ConcatenateReadWriteSecurityBuffers(
                        securityBuffers,
                        SecurityBufferType.Data);
                    cipherText = aes.Encrypt(plainText);
                }

                SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Data, cipherText);
            }
            else
            {
                cipherText = null;
            }

            //The SequenceNumber MUST be encrypted.
            //If AES is negotiated, then the server MUST use the AES-128
            //algorithm using the SessionKey with an initialization vector
            //constructed by concatenating the first 8 bytes of the
            //checksum with itself twice (thus getting 16 bytes of data)
            using (BCryptAlgorithm aes = new BCryptAlgorithm("AES"))
            {
                aes.Mode = BCryptCipherMode.CFB;
                aes.Key = sessionKey;
                aes.IV = ArrayUtility.ConcatenateArrays(
                    nlAuthSha2Sign.Checksum, // Checksum is only 8 bytes
                    nlAuthSha2Sign.Checksum);
                nlAuthSha2Sign.SequenceNumber = aes.Encrypt(nlAuthSha2Sign.SequenceNumber);
            }

            nlAuthSha2Sign.Dummy = GenerateNonce(NL_AUTH_SHA2_SIGNATURE_DUMMY_LENGTH); // 24 == size of dummy

            token = TypeMarshal.ToBytes(nlAuthSha2Sign);
            SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token, token);
        }
        /// <summary>
        /// Compute signature when AES is negotiated
        /// </summary>
        /// <param name="nlAuthSha2Sign">NL_AUTH_SHA2_SIGNATURE struct</param>
        /// <param name="sessionKey">session key</param>
        /// <param name="requestConfidentiality">confidentiality is required or not</param>
        /// <param name="plainText">plain-text message to make signature</param>
        /// <returns>signature</returns>
        private static byte[] ComputeSignatureWhenAesIsNegotiated(
            NL_AUTH_SHA2_SIGNATURE nlAuthSha2Sign,
            byte[] sessionKey,
            bool requestConfidentiality,
            byte[] plainText)
        {
            //If AES is negotiated, then a signature MUST be computed using
            //the following algorithm:
            //CALL SHA256Reset(&HashContext, Sk, sizeof(Sk));
            //CALL SHA256Input(HashContext, NL_AUTH_SHA2_SIGNATURE, [8 bytes]);
            //IF Confidentiality requested
            //CALL SHA256Input(HashContext, Confounder, [8 bytes]);
            //CALL SHA256FinalBits(HashContext, Message, size of Message;
            //CALL SHA256Result(HashContext, output);
            //SET Signature to output
            //Note: In the first call to SHA256Input, only the first 8-bytes
            //of the NL_AUTH_SHA2_SIGNATURE structure are used.
            byte[] signature;

            byte[] buf = ArrayUtility.ConcatenateArrays(
                BitConverter.GetBytes((ushort)nlAuthSha2Sign.SignatureAlgorithm),
                BitConverter.GetBytes((ushort)nlAuthSha2Sign.SealAlgorithm),
                BitConverter.GetBytes((ushort)nlAuthSha2Sign.Pad),
                BitConverter.GetBytes((ushort)nlAuthSha2Sign.Flags));

            if (requestConfidentiality)
            {
                buf = ArrayUtility.ConcatenateArrays(
                    buf,
                    nlAuthSha2Sign.Confounder);
            }

            buf = ArrayUtility.ConcatenateArrays(
                buf,
                plainText);

            using (HMACSHA256 hmacSha256 = new HMACSHA256(sessionKey))
            {
                signature = hmacSha256.ComputeHash(buf);
            }

            //After the signature is computed, the signature MUST be truncated,
            //with only the first 8 bytes being copied into the Checksum field
            //of NL_AUTH_SHA2_SIGNATURE.
            signature = ArrayUtility.SubArray(signature, 0, NL_AUTH_SIGNATURE_CHECKSUM_LENGTH);

            return signature;
        }