forked from ServiceStack/ServiceStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDigestAuthFunctions.cs
More file actions
105 lines (103 loc) · 4.9 KB
/
DigestAuthFunctions.cs
File metadata and controls
105 lines (103 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Globalization;
namespace ServiceStack.ServiceInterface.Auth
{
public class DigestAuthFunctions
{
public string PrivateHashEncode(string TimeStamp, string IPAddress, string PrivateKey)
{
var hashing = MD5.Create();
return(ConvertToHexString(hashing.ComputeHash(Encoding.UTF8.GetBytes(string.Format("{0}:{1}:{2}", TimeStamp, IPAddress, PrivateKey)))));
}
public string Base64Encode(string StringToEncode)
{
if (StringToEncode != null)
{
return Convert.ToBase64String(Encoding.UTF8.GetBytes(StringToEncode));
}
return null;
}
public string Base64Decode(string StringToDecode)
{
if (StringToDecode != null)
{
return Encoding.UTF8.GetString(Convert.FromBase64String(StringToDecode));
}
return null;
}
public string[] GetNonceParts(string nonce)
{
return Base64Decode(nonce).Split(':');
}
public string GetNonce(string IPAddress, string PrivateKey)
{
double dateTimeInMilliSeconds = (DateTime.UtcNow - DateTime.MinValue).TotalMilliseconds;
string dateTimeInMilliSecondsString = dateTimeInMilliSeconds.ToString(CultureInfo.InvariantCulture);
string privateHash = PrivateHashEncode(dateTimeInMilliSecondsString, IPAddress, PrivateKey);
return Base64Encode(string.Format("{0}:{1}", dateTimeInMilliSecondsString, privateHash));
}
public bool ValidateNonce(string nonce, string IPAddress, string PrivateKey)
{
var nonceparts = GetNonceParts(nonce);
string privateHash = PrivateHashEncode(nonceparts[0], IPAddress, PrivateKey);
return string.CompareOrdinal(privateHash, nonceparts[1]) == 0;
}
public bool StaleNonce(string nonce, int Timeout)
{
var nonceparts = GetNonceParts(nonce);
return TimeStampAsDateTime(nonceparts[0]).AddSeconds(Timeout) < DateTime.UtcNow;
}
private DateTime TimeStampAsDateTime(string TimeStamp)
{
double nonceTimeStampDouble;
if (Double.TryParse(TimeStamp, NumberStyles.Float, CultureInfo.InvariantCulture, out nonceTimeStampDouble))
{
return DateTime.MinValue.AddMilliseconds(nonceTimeStampDouble);
}
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The given nonce time stamp {0} was not valid", TimeStamp));
}
public string ConvertToHexString(IEnumerable<byte> hash)
{
var hexString = new StringBuilder();
foreach (byte byteFromHash in hash)
{
hexString.AppendFormat("{0:x2}", byteFromHash);
}
return hexString.ToString();
}
public string CreateAuthResponse(Dictionary<string, string> digestHeaders, string Ha1)
{
string Ha2 = CreateHa2(digestHeaders);
return CreateAuthResponse(digestHeaders, Ha1, Ha2);
}
public string CreateAuthResponse(Dictionary<string, string> digestHeaders, string Ha1, string Ha2)
{
string response = string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2}:{3}:{4}:{5}", Ha1, digestHeaders["nonce"], digestHeaders["nc"], digestHeaders["cnonce"], digestHeaders["qop"].ToLower(), Ha2);
return ConvertToHexString(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(response)));
}
public string CreateHa1(Dictionary<string,string> digestHeaders, string password)
{
return CreateHa1(digestHeaders["username"],digestHeaders["realm"],password);
}
public string CreateHa1(string Username, string Realm, string Password)
{
return ConvertToHexString(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(string.Format("{0}:{1}:{2}", Username,Realm,Password))));
}
public string CreateHa2(Dictionary<string, string> digestHeaders)
{
return ConvertToHexString(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(string.Format("{0}:{1}",digestHeaders["method"],digestHeaders["uri"]))));
}
public bool ValidateResponse(Dictionary<string, string> digestInfo, string PrivateKey, int NonceTimeOut, string DigestHA1, string sequence)
{
var noncevalid = ValidateNonce(digestInfo["nonce"], digestInfo["userhostaddress"], PrivateKey);
var noncestale = StaleNonce(digestInfo["nonce"], NonceTimeOut);
var uservalid = CreateAuthResponse(digestInfo, DigestHA1) == digestInfo["response"];
var sequencevalid = sequence != digestInfo["nc"];
return noncevalid && !noncestale && uservalid && sequencevalid;
}
}
}