示例#1
0
        /// <summary>
        /// Encodes <see cref="value"/> to the provided <see cref="stream"/>.
        /// </summary>
        /// <param name="stream">where to write the data</param>
        /// <param name="prevValue">the previous value if required by <see cref="UsesPreviousValue"/>. Otherwise null.</param>
        /// <param name="value">the value to encode</param>
        /// <returns>the number of bytes necessary to encode this key/value.</returns>
        public unsafe virtual int Encode(byte *stream, T prevValue, T value)
        {
            BinaryStreamPointerWrapper bs = new BinaryStreamPointerWrapper(stream, MaxCompressionSize);

            Encode(bs, prevValue, value);
            return((int)bs.Position);
        }
示例#2
0
        /// <summary>
        /// Decodes <see cref="value"/> from the provided <see cref="stream"/>.
        /// </summary>
        /// <param name="stream">where to read the data</param>
        /// <param name="prevValue">the previous value if required by <see cref="UsesPreviousValue"/>. Otherwise null.</param>
        /// <param name="value">the place to store the decoded value</param>
        /// <param name="isEndOfStream">outputs true if the end of the stream symbol is detected. Not all encoding methods have an end of stream symbol and therefore will always return false.</param>
        /// <returns>the number of bytes necessary to decode the next key/value.</returns>
        public unsafe virtual int Decode(byte *stream, T prevValue, T value, out bool isEndOfStream)
        {
            BinaryStreamPointerWrapper bs = new BinaryStreamPointerWrapper(stream, MaxCompressionSize);

            Decode(bs, prevValue, value, out isEndOfStream);
            return((int)bs.Position);
        }
示例#3
0
 public void Test7Bit4()
 {
     byte[] data = new byte[4096 * 5];
     fixed(byte *lp = data)
     {
         using (BinaryStreamPointerWrapper bs = new BinaryStreamPointerWrapper(lp, data.Length))
         {
             DebugStopwatch sw   = new DebugStopwatch();
             double         time = sw.TimeEventMedian(() =>
             {
                 for (int repeat = 0; repeat < 1000; repeat++)
                 {
                     bs.Position = 0;
                     for (int x = 0; x < 1000; x++)
                     {
                         bs.Write7Bit(128u * 128u * 128u);
                         bs.Write7Bit(128u * 128u * 128u);
                         bs.Write7Bit(128u * 128u * 128u);
                         bs.Write7Bit(128u * 128u * 128u);
                     }
                 }
             });
             Console.WriteLine(4 * 1000 * 1000 / time / 1000 / 1000);
         }
     }
 }
        /// <summary>
        /// Encodes <see cref="key"/> and <see cref="value"/> to the provided <see cref="stream"/>.
        /// </summary>
        /// <param name="stream">where to write the data</param>
        /// <param name="prevKey">the previous key if required by <see cref="UsesPreviousKey"/>. Otherwise null.</param>
        /// <param name="prevValue">the previous value if required by <see cref="UsesPreviousValue"/>. Otherwise null.</param>
        /// <param name="key">the key to encode</param>
        /// <param name="value">the value to encode</param>
        /// <returns>the number of bytes necessary to encode this key/value.</returns>
        public unsafe virtual int Encode(byte *stream, TKey prevKey, TValue prevValue, TKey key, TValue value)
        {
            var bs = new BinaryStreamPointerWrapper(stream, MaxCompressionSize);

            Encode(bs, prevKey, prevValue, key, value);
            return((int)bs.Position);
        }
        public void TestWriteLong()
        {
            byte[] data = new byte[4096 * 8];
            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.Write((long)x);
                                bs.Write((long)x);
                                bs.Write((long)x);
                                bs.Write((long)x);
                            }
                        }
                    });

                    Console.WriteLine((4 * 1000 * 1000) / time / 1000 / 1000);
                }
            }
        }
        private unsafe void CreateResumeTicket(Guid userToken, out byte[] ticket, out byte[] sessionSecret)
        {
#if SQLCLR
            ticket        = null;
            sessionSecret = null;
#else
            State state = m_state;

            //Ticket Structure:
            //  byte      TicketVersion = 1
            //  Guid      ServerKeyName
            //  DateTime  AuthenticationTime
            //  byte[16]  IV
            //  byte[]    Encrypted Session Data 32+16
            //  byte[32]  HMAC (Sha2-256)

            const int encryptedLength = 32 + 16;
            const int ticketSize      = 1 + 16 + 8 + 16 + encryptedLength + 32;

            byte[] initializationVector = SaltGenerator.Create(16);
            sessionSecret = SaltGenerator.Create(32);
            byte[] userTokenBytes = userToken.ToRfcBytes();
            byte[] dataToEncrypt  = new byte[encryptedLength];
            sessionSecret.CopyTo(dataToEncrypt, 0);
            userTokenBytes.CopyTo(dataToEncrypt, sessionSecret.Length);
            ticket = new byte[ticketSize];

            using (Aes aes = Cipher.CreateAes())
            {
                aes.Key     = state.ServerEncryptionkey;
                aes.IV      = initializationVector;
                aes.Mode    = CipherMode.CBC;
                aes.Padding = PaddingMode.None;
                ICryptoTransform decrypt       = aes.CreateEncryptor();
                byte[]           encryptedData = decrypt.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);

                fixed(byte *lp = ticket)
                {
                    BinaryStreamPointerWrapper stream = new BinaryStreamPointerWrapper(lp, ticket.Length);

                    stream.Write((byte)1);
                    stream.Write(state.ServerKeyName);
                    stream.Write(DateTime.UtcNow.RoundDownToNearestMinute());
                    stream.Write(initializationVector);
                    stream.Write(encryptedData); //Encrypted data, 32 byte session key, n byte user token
                    stream.Write(HMAC <Sha256Digest> .Compute(state.ServerHMACKey, ticket, 0, ticket.Length - 32));
                }
            }
#endif
        }
示例#7
0
        private 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. (Effectively 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];

            using (Aes aes = Cipher.CreateAes())
            {
                aes.Key     = user.ServerEncryptionkey;
                aes.IV      = initializationVector;
                aes.Mode    = CipherMode.CBC;
                aes.Padding = PaddingMode.None;
                ICryptoTransform decrypt       = aes.CreateEncryptor();
                byte[]           encryptedData = decrypt.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);

                fixed(byte *lp = ticket)
                {
                    using (BinaryStreamPointerWrapper 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);
        }
示例#8
0
        /// <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);
            }
        }
示例#9
0
        /// <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);
        }
示例#10
0
        /// <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);
        }
示例#11
0
        private unsafe bool TryLoadTicket(byte[] ticket, out byte[] sessionSecret, out Guid userToken)
        {
#if SQLCLR
            sessionSecret = null;
            userToken     = Guid.Empty;
            return(false);
#else
            State     state           = m_state;
            const int encryptedLength = 32 + 16;
            const int ticketSize      = 1 + 16 + 8 + 16 + encryptedLength + 32;

            userToken     = default(Guid);
            sessionSecret = null;

            //Ticket Structure:
            //  byte      TicketVersion = 1
            //  Guid      ServerKeyName
            //  DateTime  AuthenticationTime
            //  byte[16]  IV
            //  byte[]    Encrypted Session Data 32+16
            //  byte[32]  HMAC (Sha2-256)

            if (ticket == null || ticket.Length != ticketSize)
                return(false);

            fixed(byte *lp = ticket)
            {
                var stream = new BinaryStreamPointerWrapper(lp, ticket.Length);

                if (stream.ReadUInt8() != 1)
                {
                    return(false);
                }

                if (!state.ServerKeyName.SecureEquals(stream.ReadGuid()))
                {
                    return(false);
                }


                long currentTime = DateTime.UtcNow.Ticks;
                long issueTime   = stream.ReadInt64();


                if (issueTime <= currentTime)
                {
                    //Issue time is before current time.
                    if (currentTime - issueTime > TimeSpan.TicksPerMinute * TicketExpireTimeMinutes)
                    {
                        return(false);
                    }
                }
                else
                {
                    //For some reason, the issue time is after the current time.
                    //This could be due to a clock sync on the server after the ticket was issued.
                    //Allow up to 1 minute of clock skew
                    if (issueTime - currentTime > TimeSpan.TicksPerMinute)
                    {
                        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(state.ServerHMACKey, ticket, 0, ticket.Length - 32);

                if (!hmac.SecureEquals(ticket, ticket.Length - 32, 32))
                {
                    return(false);
                }

                byte[] encryptedData = stream.ReadBytes(encryptedLength);
                var    aes           = new RijndaelManaged();

                aes.Key     = state.ServerEncryptionkey;
                aes.IV      = initializationVector;
                aes.Mode    = CipherMode.CBC;
                aes.Padding = PaddingMode.None;
                var decrypt = aes.CreateDecryptor();

                encryptedData = decrypt.TransformFinalBlock(encryptedData, 0, encryptedData.Length);

                sessionSecret = new byte[32];
                Array.Copy(encryptedData, 0, sessionSecret, 0, 32);
                userToken = encryptedData.ToRfcGuid(32);

                return(true);
            }
#endif
        }