private static byte[] Encrypt(ulong sessionId, Smb2CryptoInfo cryptoInfo, Smb2Role role, Smb2Packet originalPacket)
        {
            Packet_Header header;

            if (originalPacket is Smb2SinglePacket)
            {
                header = (originalPacket as Smb2SinglePacket).Header;
            }
            else
            {
                header = (originalPacket as Smb2CompoundPacket).Packets[0].Header;
            }

            // Encrypt all messages after session setup if global encryption enabled.
            // Encrypt all messages after tree connect if global encryption disabled but share encryption enabled.
            if ((cryptoInfo.EnableSessionEncryption ||
                 (cryptoInfo.EnableTreeEncryption.Contains(header.TreeId) &&
                  header.Command != Smb2Command.TREE_CONNECT
                 )
                 )
                )
            {
                using (var bcrypt = new BCryptAlgorithm("AES"))
                {
                    byte[]           originalBinary  = originalPacket.ToBytes();
                    Transform_Header transformHeader = new Transform_Header
                    {
                        ProtocolId          = Smb2Consts.ProtocolIdInTransformHeader,
                        OriginalMessageSize = (uint)originalBinary.Length,
                        SessionId           = sessionId,
                        Signature           = new byte[16]
                    };

                    if (cryptoInfo.Dialect == DialectRevision.Smb311)
                    {
                        transformHeader.Flags = TransformHeaderFlags.Encrypted;
                    }
                    else
                    {
                        transformHeader.EncryptionAlgorithm = EncryptionAlgorithm.ENCRYPTION_AES128_CCM;
                    }

                    byte[] tag;

                    int nonceLength       = 0;
                    BCryptCipherMode mode = BCryptCipherMode.NotAvailable;
                    GetCryptoParams(cryptoInfo, CryptoOperationType.Encrypt, out mode, out nonceLength);
                    bcrypt.Mode = mode;
                    bcrypt.Key  = role == Smb2Role.Server ? cryptoInfo.ServerOutKey : cryptoInfo.ServerInKey;
                    // The reserved field (5 bytes for CCM, 4 bytes for GCM) must be set to zero.
                    byte[] nonce = new byte[16];
                    Buffer.BlockCopy(Guid.NewGuid().ToByteArray(), 0, nonce, 0, nonceLength);
                    transformHeader.Nonce = new Guid(nonce);

                    byte[] output = bcrypt.Encrypt(
                        originalBinary,
                        transformHeader.Nonce.ToByteArray().Take(nonceLength).ToArray(),
                        // Use the fields including and after Nonce field as auth data
                        Smb2Utility.MarshalStructure(transformHeader).Skip(20).ToArray(),
                        // Signature is 16 bytes in length
                        16,
                        out tag);
                    transformHeader.Signature = tag;
                    return(Smb2Utility.MarshalStructure(transformHeader).Concat(output).ToArray());
                }
            }

            // Return null if the message is not required to be encrypted.
            return(null);
        }