Ejemplo n.º 1
0
        /// <summary>
        /// Constructs an instance by parsing a serialized string.
        /// </summary>
        /// <param name="serialized">The serialized visitor information.</param>
        /// <exception cref="ArgumentNullException">Thrown if <c>null</c> is passed.</exception>
        /// <exception cref="ArgumentException">Thrown if the parameter passed does not represent a valid <see cref="UniqueVisitor" /> instance.</exception>
        /// <remarks>
        /// <para>
        /// The <paramref name="serialized" /> value must have been generated by
        /// a previous call to <see cref="ToString" />.
        /// </para>
        /// </remarks>
        public UniqueVisitor(string serialized)
        {
            if (serialized == null)
            {
                throw new ArgumentNullException("serialized");
            }

            try
            {
                using (var ms = new EnhancedMemoryStream(Convert.FromBase64String(serialized)))
                {
                    if (ms.ReadInt16() != Magic)
                    {
                        throw new FormatException("Bad magic number.");
                    }

                    this.IssueDateUtc = new DateTime(ms.ReadInt64(), DateTimeKind.Utc);
                    this.ID           = new Guid(ms.ReadBytes(32));
                }
            }
            catch (Exception e)
            {
                throw new ArgumentException("Invalid unique serialized visitor.", "seralized", e);
            }
        }
Ejemplo n.º 2
0
        public void EnhancedMemoryStream_ReadWriteBytesNoLen()
        {
            var es = new EnhancedMemoryStream();

            es.WriteBytesNoLen(new byte[] { 0, 1, 2, 3 });
            es.Seek(0, SeekOrigin.Begin);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3 }, es.ReadBytes(4));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Verifies request arguments against a signature using a shared <see cref="SymmetricKey" />
        /// and the current time.
        /// </summary>
        /// <param name="sharedKey">The shared <see cref="SymmetricKey" />.</param>
        /// <param name="signature">The base-64 encoded signature.</param>
        /// <param name="args">The request argument collection.</param>
        /// <param name="signatureKey">
        /// The name of the signature key within the event arguments or <c>null</c>
        /// if the signature is not present.
        /// </param>
        /// <param name="graceInterval">Specifies the time period used for verifying the signature request time.</param>
        /// <returns><c>true</c> if the signature is valid.</returns>
        /// <remarks>
        /// <para>
        /// <paramref name="graceInterval" /> is used when comparing the request time (UTC) embedded
        /// in the signature with the current machine time (UTC).  Request times within the range of:
        /// </para>
        /// <code language="none">
        /// DateTime.UtcNow - graceInterval &lt;= requestTime &lt;= DateTime.UtcNow + graceInterval
        /// </code>
        /// <para>
        /// will be considered to be valid.  Request times outside this range will be invalid.
        /// Larger grace intervals provide help avoid the problems of incorrect system times or
        /// long request delivery delays but at the price of the increased exposure to replay
        /// attacks.
        /// </para>
        /// <note>
        /// If the signature is present in the arguments, then the <paramref name="signatureKey" /> <b>must</b>
        /// be passed as its name or else the verification will always fail.  The reason for this is
        /// that the hash was originally computed before the signature was added so the hash will be
        /// different if it includes the signature.
        /// </note>
        /// </remarks>
        public static bool TryVerify(SymmetricKey sharedKey, string signature, ArgCollection args, string signatureKey, TimeSpan graceInterval)
        {
            try
            {
                byte[]   encrypted = Convert.FromBase64String(signature);
                byte[]   decrypted;
                byte[]   requestHash;
                byte[]   hash;
                DateTime requestTime;
                DateTime now;

                decrypted = Crypto.Decrypt(encrypted, sharedKey);
                if (decrypted.Length != Size)
                {
                    return(false);
                }

                using (var ms = new EnhancedMemoryStream(decrypted))
                {
                    ms.Position = 8;
                    if (ms.ReadInt32() != Magic)
                    {
                        return(false);
                    }

                    requestTime = new DateTime(ms.ReadInt64());
                    requestHash = ms.ReadBytes(SHA1Hasher.DigestSize);
                }

                now = DateTime.UtcNow;
                if (!Helper.Within(requestTime, now, graceInterval))
                {
                    return(false);
                }

                hash = ComputeHash(args, signatureKey);
                return(Helper.ArrayEquals(requestHash, hash));
            }
            catch
            {
                return(false);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Decrypts and deserializes a message from a byte buffer.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="sharedKey">The shared encryption key.</param>
        /// <exception cref="FormatException">Thrown if the buffer does not contain a valid message.</exception>
        public UdpBroadcastMessage(byte[] buffer, SymmetricKey sharedKey)
        {
            try
            {
                using (var ms = new EnhancedMemoryStream(Crypto.Decrypt(buffer, sharedKey)))
                {
                    if (ms.ReadInt32Le() != Magic)
                    {
                        throw new Exception();
                    }

                    this.TimeStampUtc   = new DateTime(ms.ReadInt64Le());
                    this.SourceAddress  = new IPAddress(ms.ReadBytes(4));
                    this.MessageType    = (UdpBroadcastMessageType)ms.ReadByte();
                    this.BroadcastGroup = ms.ReadByte();
                    this.Payload        = ms.ReadBytes16();
                }
            }
            catch (Exception e)
            {
                throw new FormatException("Invalid UDP broadcast message.", e);
            }
        }