Creates a BinaryStreamBase that wraps a single pointer.
상속: BinaryStreamPointerBase
        public void Test7Bit3()
        {
            byte[] data = new byte[4096 * 5];
            fixed (byte* lp = data)
            {
                using (var bs = new BinaryStreamPointerWrapper(lp, data.Length))
                {
                    DebugStopwatch sw = new DebugStopwatch();
                    var time = sw.TimeEventMedian(() =>
                    {
                        for (int repeat = 0; repeat < 1000; repeat++)
                        {
                            bs.Position = 0;
                            for (int x = 0; x < 1000; x++)
                            {
                                bs.Write7Bit(128u * 128u);
                                bs.Write7Bit(128u * 128u);
                                bs.Write7Bit(128u * 128u);
                                bs.Write7Bit(128u * 128u);
                            }
                        }

                    });
                    Console.WriteLine((4 * 1000 * 1000) / time / 1000 / 1000);
                }
            }
        }
 /// <summary>
 /// Writes the key to the stream
 /// </summary>
 /// <param name="stream"></param>
 public virtual unsafe void Write(byte* stream)
 {
     var writer = new BinaryStreamPointerWrapper(stream, Size);
     Write(writer);
 }
        /// <summary>
        /// Attempts to load the session resume ticket.
        /// </summary>
        /// <param name="ticket">The serialized data for the key</param>
        /// <param name="user">The user's credentials so the proper encryption key can be used</param>
        /// <param name="sessionSecret">the session secret decoded if successful. null otherwise</param>
        /// <returns>
        /// True if the ticket is authentic
        /// </returns>
        unsafe static bool TryLoadTicket(byte[] ticket, SrpUserCredential user, out byte[] sessionSecret)
        {
            sessionSecret = null;

            //Ticket Structure:
            //  byte      TicketVersion = 1
            //  int16     Username Length
            //  int16     Session Key Length 
            //  Guid      ServerKeyName
            //  DateTime  AuthenticationTime
            //  byte[16]  IV
            //  byte[]    Username
            //  byte[]    Encrypted Session Data (Round [Session Key Length] up to a 128 bit number to get the length of the encrypted data)
            //  byte[32]  HMAC (Sha2-256)

            if (ticket == null || ticket.Length < 1 + 16 + 8 + 16 + 2 + 32)
                return false;

            fixed (byte* lp = ticket)
            {
                var stream = new BinaryStreamPointerWrapper(lp, ticket.Length);
                if (stream.ReadUInt8() != 1)
                    return false;

                int sessionKeyLength = stream.ReadUInt16();
                if (sessionKeyLength < 0 || sessionKeyLength > 1024) //Max session key is 8192 SRP.
                    return false;

                int encryptedDataLength = (sessionKeyLength + 15) & ~15; //Add 15, then round down. (Effecitvely rounds up to the nearest 128 bit boundary).
                if (ticket.Length != 1 + 2 + 16 + 8 + 16 + encryptedDataLength + 32)
                    return false;

                if (!user.ServerKeyName.SecureEquals(stream.ReadGuid()))
                    return false;

                long maxTicketAge = DateTime.UtcNow.Ticks + TimeSpan.TicksPerMinute * 10; //Allows for time syncing issues that might move the server's time back by a few minutes.
                long minTicketAge = maxTicketAge - TimeSpan.TicksPerDay;

                long issueTime = stream.ReadInt64();
                if (issueTime < minTicketAge || issueTime > maxTicketAge)
                    return false;

                byte[] initializationVector = stream.ReadBytes(16);

                //Verify the signature if everything else looks good.
                //This is last because it is the most computationally complex.
                //This limits denial of service attackes.
                byte[] hmac = HMAC<Sha256Digest>.Compute(user.ServerHMACKey, ticket, 0, ticket.Length - 32);
                if (!hmac.SecureEquals(ticket, ticket.Length - 32, 32))
                    return false;

                byte[] encryptedData = stream.ReadBytes(encryptedDataLength);
                var aes = new RijndaelManaged();
                aes.Key = user.ServerEncryptionkey;
                aes.IV = initializationVector;
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.None;
                var decrypt = aes.CreateDecryptor();
                sessionSecret = decrypt.TransformFinalBlock(encryptedData, 0, encryptedData.Length);

                return true;
            }
        }
 /// <summary>
 /// Reads the key from the stream
 /// </summary>
 /// <param name="stream"></param>
 public virtual unsafe void Read(byte* stream)
 {
     var reader = new BinaryStreamPointerWrapper(stream, Size);
     Read(reader);
 }
        static unsafe byte[] CreateSessionData(byte[] sessionSecret, SrpUserCredential user)
        {
            byte[] initializationVector = SaltGenerator.Create(16);
            int len = sessionSecret.Length;
            int blockLen = (len + 15) & ~15; //Add 15, then round down. (Effecitvely rounds up to the nearest 128 bit boundary).
            byte[] dataToEncrypt = new byte[blockLen];
            sessionSecret.CopyTo(dataToEncrypt, 0);

            //fill the remainder of the block with random bits
            if (len != blockLen)
            {
                SaltGenerator.Create(blockLen - len).CopyTo(dataToEncrypt, len);
            }

            byte[] ticket = new byte[1 + 16 + 8 + 16 + 2 + blockLen + 32];

            var aes = new RijndaelManaged();
            aes.Key = user.ServerEncryptionkey;
            aes.IV = initializationVector;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.None;
            var decrypt = aes.CreateEncryptor();
            var encryptedData = decrypt.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);

            fixed (byte* lp = ticket)
            {
                var stream = new BinaryStreamPointerWrapper(lp, ticket.Length);
                stream.Write((byte)1);
                stream.Write((short)len);
                stream.Write(user.ServerKeyName);
                stream.Write(DateTime.UtcNow);
                stream.Write(initializationVector);
                stream.Write(encryptedData);
                stream.Write(HMAC<Sha256Digest>.Compute(user.ServerHMACKey, ticket, 0, ticket.Length - 32));
            }
            return ticket;
        }