/// <summary> Encodes a millisecond value and ip address along with the given private key to be used in a nonce. </summary> /// <remarks> ebrown, 4/6/2011. </remarks> /// <exception cref="ArgumentNullException"> Thrown when one or more required arguments are null. </exception> /// <exception cref="ArgumentException"> Thrown when one or more arguments have unsupported or illegal values. </exception> /// <param name="dateTimeInMilliseconds"> The milliseconds as a string. </param> /// <param name="ipAddress"> The IP address. </param> /// <returns> A MD5 hashed string containing the above values. </returns> public string Encode(string dateTimeInMilliseconds, string ipAddress) { if (null == ipAddress) { throw new ArgumentNullException("ipAddress"); } if (string.IsNullOrWhiteSpace(ipAddress)) { throw new ArgumentException("value must be non-whitespace", "ipAddress"); } if (null == dateTimeInMilliseconds) { throw new ArgumentNullException("dateTimeInMilliseconds"); } if (string.IsNullOrWhiteSpace(dateTimeInMilliseconds)) { throw new ArgumentException("value must be non-whitespace", "dateTimeInMilliseconds"); } string stringToEncode = string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2}", dateTimeInMilliseconds, ipAddress, _privateKey); using (var algorithm = MD5.Create()) { return(HashHelpers.SafeHash(algorithm, stringToEncode)); } }
/// <summary> Matches credentials. </summary> /// <remarks> ebrown, 3/28/2011. </remarks> /// <exception cref="ArgumentNullException"> Thrown when realm, nonce or password are null. </exception> /// <exception cref="NotImplementedException"> Thrown when the current DigestHeader is set to 'auth-int', which is presently /// unsupported. </exception> /// <exception cref="NotSupportedException"> Thrown when the DigestHeaders HTTP method is unrecognized or not supported. </exception> /// <param name="realm"> The realm. </param> /// <param name="opaque"> The opaque. </param> /// <param name="password"> The password. </param> /// <returns> true if it succeeds, false if it fails. </returns> public bool MatchesCredentials(string realm, string opaque, string password) { if (null == realm) { throw new ArgumentNullException("realm"); } if (null == password) { throw new ArgumentNullException("password"); } if (DigestQualityOfProtectionType.AuthenticationWithIntegrity == QualityOfProtection) { throw new NotImplementedException("auth-int is not currently supported"); } if (!Verb.IsEnumFromEnumValue <HttpMethodNames>()) { throw new NotSupportedException(String.Format("The verb {0} specified is not valid", Verb)); } var encoding = Encoding.GetEncoding("ISO-8859-1"); using (var algorithm = MD5.Create()) { //client to server opaque must match if (Opaque != opaque) { return(false); } //client to server realm must match if (realm != Realm) { return(false); } //valid for auth, auth-int and unspecified string hash1 = HashHelpers.SafeHash(algorithm, encoding.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2}", UserName, Realm, password))); //valid for auth and unspecified string hash2 = HashHelpers.SafeHash(algorithm, encoding.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}:{1}", Verb, Uri))); if (QualityOfProtection == DigestQualityOfProtectionType.Authentication) { return(Response == HashHelpers.SafeHash(algorithm, encoding.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2:00000000.##}:{3}:{4}:{5}", hash1, Nonce, RequestCounter, ClientNonce, QualityOfProtection.ToEnumValueString(), hash2)))); } return(Response == HashHelpers.SafeHash(algorithm, encoding.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2}", hash1, Nonce, hash2)))); } }