public void EnhancedMemoryStream_Int64() { var es = new EnhancedMemoryStream(); es.WriteInt64(0); es.WriteInt64(65121); es.WriteInt64(0x12345678); es.WriteInt64((((long)0x12345678) << 32) | (long)0xaabbccddee); es.Seek(0, SeekOrigin.Begin); Assert.AreEqual(0, es.ReadInt64()); Assert.AreEqual(65121, es.ReadInt64()); Assert.AreEqual(0x12345678, es.ReadInt64()); Assert.AreEqual((((long)0x12345678) << 32) | (long)0xaabbccddee, es.ReadInt64()); }
/// <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); } }
/// <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 <= requestTime <= 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); } }