5
// Bojan Rajkovic <bojanr@brandeis.edu>
6
// Shannon Whitley <swhitley@whitleymedia.com>
7
// Eran Sandler <http://eran.sandler.co.il/>
8
// Sandy Armstrong <sanfordarmstrong@gmail.com>
10
// Copyright (c) 2009 Bojan Rajkovic
12
// Permission is hereby granted, free of charge, to any person obtaining a copy
13
// of this software and associated documentation files (the "Software"), to deal
14
// in the Software without restriction, including without limitation the rights
15
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
// copies of the Software, and to permit persons to whom the Software is
17
// furnished to do so, subject to the following conditions:
19
// The above copyright notice and this permission notice shall be included in
20
// all copies or substantial portions of the Software.
22
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
using System.Collections.Generic;
34
using System.Security.Cryptography;
41
/// Provides a base class for OAuth authentication and signing.
47
public void LogDebug (string format, params object[] objects)
50
Tomboy.Logger.Debug (format, objects);
53
public bool Debugging { get; set; }
56
private readonly LoggerAdapter log = new LoggerAdapter ();
57
private bool debugging;
61
get { return debugging; }
62
set { debugging = value; log.Debugging = value; }
65
private const string OAuthVersion = "1.0";
68
// List of know and used oauth parameters' names
70
private const string OAuthConsumerKeyKey = "oauth_consumer_key";
71
private const string OAuthCallbackKey = "oauth_callback";
72
private const string OAuthVersionKey = "oauth_version";
73
private const string OAuthSignatureMethodKey = "oauth_signature_method";
74
private const string OAuthSignatureKey = "oauth_signature";
75
private const string OAuthTimestampKey = "oauth_timestamp";
76
private const string OAuthNonceKey = "oauth_nonce";
77
private const string OAuthTokenKey = "oauth_token";
78
private const string OAuthTokenSecretKey = "oauth_token_secret";
79
private const string OAuthVerifierKey = "oauth_verifier";
81
private const string HMACSHA1SignatureType = "HMAC-SHA1";
82
private const string PlainTextSignatureType = "PLAINTEXT";
83
private const string RSASHA1SignatureType = "RSA-SHA1";
85
private Random random = new Random ();
87
private string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
90
/// Helper function to compute a hash value.
92
/// <param name="hashAlgorithm">
93
/// The hashing algoirhtm used. If that algorithm needs some initialization, like HMAC and its derivatives,
94
/// they should be initialized prior to passing it to this function.
96
/// <param name="data">The data to hash.</param>
97
/// <returns>A Base64 string of the hash value.</returns>
98
private string ComputeHash (HashAlgorithm hashAlgorithm, string data)
100
log.LogDebug ("Computing hash for data {0}", data);
102
if (hashAlgorithm == null) throw new ArgumentNullException ("hashAlgorithm");
103
if (string.IsNullOrEmpty (data)) throw new ArgumentNullException ("data");
105
byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes (data);
106
byte[] hashBytes = hashAlgorithm.ComputeHash (dataBuffer);
108
return Convert.ToBase64String (hashBytes);
112
/// URL encodes a string using OAuth's encoding scheme (slightly different from HttpUtility's UrlEncode).
114
/// <param name="value">The string to URL encode.</param>
115
/// <returns>An URL encoded string.</returns>
116
private string UrlEncode (string value)
118
log.LogDebug ("URL encoding value.");
119
var result = new StringBuilder ();
121
foreach (char symbol in value) {
122
if (unreservedChars.IndexOf(symbol) != -1) result.Append(symbol);
123
else result.Append('%' + String.Format("{0:X2}", (int)symbol));
126
return result.ToString();
130
/// Internal function to cut out all non oauth query string parameters.
132
/// <param name="parameters">The query string part of the URL.</param>
133
/// <returns>A list of QueryParameter each containing the parameter name and value.</returns>
134
private IEnumerable<IQueryParameter<string>> GetQueryParameters (string parameters)
136
log.LogDebug ("Creating list of parameters from parameter string {0}", parameters);
138
return CreateQueryParametersIterator (parameters);
141
private IEnumerable<IQueryParameter<string>> CreateQueryParametersIterator (string parameters)
143
if (parameters == null) throw new ArgumentNullException ("parameters");
144
var parameterDictionary = HttpUtility.ParseQueryString (parameters).ToDictionary ();
146
foreach (var kvp in parameterDictionary)
147
yield return new QueryParameter<string> (kvp.Key, kvp.Value, s => string.IsNullOrEmpty (s));
151
/// Generate the signature base that is used to produce the signature
153
/// <param name="url">The full URL that needs to be signed including its non OAuth URL parameters.</param>
154
/// <param name="consumerKey">The consumer key.</param>
155
/// <param name="token">The token, if available. If not available pass null or an empty string.</param>
156
/// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string.</param>
157
/// <param name="verifier">The callback verifier, if available. If not available pass null or an empty string.</param>
158
/// <param name="httpMethod">The HTTP method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
159
/// <param name="signatureType">The signature type. To use the default values use <see cref="SignatureType">SignatureType</see>.</param>
160
/// <returns>The signature base.</returns>
161
private string GenerateSignatureBase (Uri url, string consumerKey, string token, string tokenSecret, string verifier,
162
RequestMethod method, TimeSpan timeStamp, string nonce, SignatureType signatureType, out string normalizedUrl,
163
out List<IQueryParameter<string>> parameters)
165
log.LogDebug ("Generating signature base for OAuth request.");
167
token = token ?? string.Empty;
168
tokenSecret = tokenSecret ?? string.Empty;
169
verifier = verifier ?? String.Empty;
171
if (consumerKey == null) throw new ArgumentNullException ("consumerKey");
173
log.LogDebug ("URL: {0}", url.Query);
175
var signatureString = string.Empty;
177
switch (signatureType) {
178
case SignatureType.HMACSHA1:
179
signatureString = "HMAC-SHA1";
181
case SignatureType.RSASHA1:
182
signatureString = "RSA-SHA1";
184
case SignatureType.PLAINTEXT:
185
signatureString = SignatureType.PLAINTEXT.ToString ();
189
parameters = GetQueryParameters (url.Query).Concat (new List<IQueryParameter<string>> {
190
new QueryParameter<string> (OAuthVersionKey, OAuthVersion, s => string.IsNullOrEmpty (s)),
191
new QueryParameter<string> (OAuthTimestampKey, ((long)timeStamp.TotalSeconds).ToString (), s => string.IsNullOrEmpty (s)),
192
new QueryParameter<string> (OAuthSignatureMethodKey, signatureString, s => string.IsNullOrEmpty (s)),
193
new QueryParameter<string> (OAuthNonceKey, nonce, s => string.IsNullOrEmpty (s)),
194
new QueryParameter<string> (OAuthConsumerKeyKey, consumerKey, s => string.IsNullOrEmpty (s))
197
if (!string.IsNullOrEmpty (token)) parameters.Add (new QueryParameter<string> (OAuthTokenKey, token, s => string.IsNullOrEmpty (s)));
198
if (!string.IsNullOrEmpty (verifier)) parameters.Add (new QueryParameter<string> (OAuthVerifierKey, verifier, s => string.IsNullOrEmpty (s)));
200
log.LogDebug ("Normalizing URL for signature.");
202
normalizedUrl = string.Format ("{0}://{1}", url.Scheme, url.Host);
203
if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) normalizedUrl += ":" + url.Port;
204
normalizedUrl += url.AbsolutePath;
206
log.LogDebug ("Generated normalized URL: {0}", normalizedUrl);
207
log.LogDebug ("Normalizing request parameters.");
210
string normalizedRequestParameters = parameters.NormalizeRequestParameters ();
212
log.LogDebug ("Normalized request parameters {0}.", normalizedRequestParameters);
213
log.LogDebug ("Generating signature base from normalized URL and request parameters.");
215
var signatureBase = new StringBuilder ();
216
signatureBase.AppendFormat("{0}&", method.ToString ());
217
signatureBase.AppendFormat("{0}&", UrlEncode (normalizedUrl));
218
signatureBase.AppendFormat("{0}", UrlEncode (normalizedRequestParameters));
220
log.LogDebug ("Signature base: {0}", signatureBase.ToString ());
222
return signatureBase.ToString ();
226
/// Generate the signature value based on the given signature base and hash algorithm.
228
/// <param name="signatureBase">
229
/// The signature based as produced by the GenerateSignatureBase method or by any other means.
231
/// <param name="hash">
232
/// The hash algorithm used to perform the hashing. If the hashing algorithm requires
233
/// initialization or a key it should be set prior to calling this method.
235
/// <returns>A Base64 string of the hash value.</returns>
236
private string GenerateSignatureUsingHash (string signatureBase, HashAlgorithm hash)
238
log.LogDebug ("Generating hashed signature.");
239
return ComputeHash (hash, signatureBase);
243
/// Generates a signature using the HMAC-SHA1 algorithm
245
/// <param name="url">The full URL that needs to be signed including its non-OAuth URL parameters.</param>
246
/// <param name="consumerKey">The consumer key.</param>
247
/// <param name="consumerSecret">The consumer seceret.</param>
248
/// <param name="token">The token, if available. If not available pass null or an empty string.</param>
249
/// <param name="tokenSecret">The token secret, if available. If not, pass null or an empty string.</param>
250
/// <param name="verifier">The callback verifier, if available. If not, pass null or an empty string.</param>
251
/// <param name="httpMethod">The HTTP method used. Must be valid HTTP method verb (POST, GET, PUT, etc).</param>
252
/// <returns>A Base64 string of the hash value.</returns>
253
protected string GenerateSignature (Uri url, string consumerKey, string consumerSecret, string token,
254
string tokenSecret, string verifier, RequestMethod method, TimeSpan timeStamp, string nonce, out string normalizedUrl,
255
out List<IQueryParameter<string>> parameters)
257
log.LogDebug ("Generating signature using HMAC-SHA1 algorithm.");
258
return GenerateSignature (url, consumerKey, consumerSecret, token, tokenSecret, verifier, method, timeStamp, nonce,
259
SignatureType.HMACSHA1, out normalizedUrl, out parameters);
263
/// Generates a signature using the specified signature type.
265
/// <param name="url">The full URL that needs to be signed including its non-OAuth URL parameters.</param>
266
/// <param name="consumerKey">The consumer key.</param>
267
/// <param name="consumerSecret">The consumer seceret.</param>
268
/// <param name="token">The token, if available. If not available pass null or an empty string.</param>
269
/// <param name="tokenSecret">The token secret, if available. If not, pass null or an empty string.</param>
270
/// <param name="verifier">The callback verifier, if available. If not, pass null or an empty string.</param>
271
/// <param name="httpMethod">The HTTP method used. Must be a valid HTTP method verb (POST,GET,PUT, etc).</param>
272
/// <param name="signatureType">The type of signature to use.</param>
273
/// <returns>A Base64 string of the hash value.</returns>
274
private string GenerateSignature (Uri url, string consumerKey, string consumerSecret, string token,
275
string tokenSecret, string verifier, RequestMethod method, TimeSpan timeStamp, string nonce, SignatureType signatureType,
276
out string normalizedUrl, out List<IQueryParameter<string>> parameters)
278
log.LogDebug ("Generating signature using signature type {0}", signatureType);
280
normalizedUrl = null;
283
switch (signatureType)
285
case SignatureType.PLAINTEXT:
286
var signature = UrlEncode (string.Format ("{0}&{1}", consumerSecret, tokenSecret));
287
log.LogDebug ("Plaintext encoding signature {0} of consumer secret and token secret.", signature);
289
case SignatureType.HMACSHA1:
290
string signatureBase = GenerateSignatureBase (url, consumerKey, token, tokenSecret, verifier, method,
291
timeStamp, nonce, SignatureType.HMACSHA1, out normalizedUrl, out parameters);
293
var hmacsha1 = new HMACSHA1 ();
294
hmacsha1.Key = Encoding.ASCII.GetBytes (string.Format ("{0}&{1}",
295
UrlEncode (consumerSecret),
296
string.IsNullOrEmpty (tokenSecret) ? "" : UrlEncode(tokenSecret)));
298
var hashedSignature = GenerateSignatureUsingHash (signatureBase, hmacsha1);
300
log.LogDebug ("HMAC-SHA1 encoded signature {0} of consumer secret and token secret.", hashedSignature);
301
return hashedSignature;
302
case SignatureType.RSASHA1:
303
throw new NotImplementedException ();
305
throw new ArgumentException ("Unknown signature type", "signatureType");
310
/// Generate the timestamp for the signature.
312
/// <returns>A string timestamp.</returns>
313
protected TimeSpan GenerateTimeStamp ()
315
log.LogDebug ("Generating time stamp.");
316
// Default implementation of UNIX time of the current UTC time
317
return DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
321
/// Generate a nonce.
323
/// <returns>A random nonce string.</returns>
324
protected virtual string GenerateNonce()
326
log.LogDebug ("Generating nonce.");
327
// Just a simple implementation of a random number between 123400 and 9999999
328
return random.Next (123400, 9999999).ToString ();
5
// Bojan Rajkovic <bojanr@brandeis.edu>
6
// Shannon Whitley <swhitley@whitleymedia.com>
7
// Eran Sandler <http://eran.sandler.co.il/>
8
// Sandy Armstrong <sanfordarmstrong@gmail.com>
10
// Copyright (c) 2009 Bojan Rajkovic
12
// Permission is hereby granted, free of charge, to any person obtaining a copy
13
// of this software and associated documentation files (the "Software"), to deal
14
// in the Software without restriction, including without limitation the rights
15
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
// copies of the Software, and to permit persons to whom the Software is
17
// furnished to do so, subject to the following conditions:
19
// The above copyright notice and this permission notice shall be included in
20
// all copies or substantial portions of the Software.
22
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
using System.Collections.Generic;
34
using System.Security.Cryptography;
41
/// Provides a base class for OAuth authentication and signing.
47
public void LogDebug (string format, params object[] objects)
50
Tomboy.Logger.Debug (format, objects);
53
public bool Debugging { get; set; }
56
private readonly LoggerAdapter log = new LoggerAdapter ();
57
private bool debugging;
61
get { return debugging; }
62
set { debugging = value; log.Debugging = value; }
65
private const string OAuthVersion = "1.0";
68
// List of know and used oauth parameters' names
70
private const string OAuthConsumerKeyKey = "oauth_consumer_key";
71
private const string OAuthCallbackKey = "oauth_callback";
72
private const string OAuthVersionKey = "oauth_version";
73
private const string OAuthSignatureMethodKey = "oauth_signature_method";
74
private const string OAuthSignatureKey = "oauth_signature";
75
private const string OAuthTimestampKey = "oauth_timestamp";
76
private const string OAuthNonceKey = "oauth_nonce";
77
private const string OAuthTokenKey = "oauth_token";
78
private const string OAuthTokenSecretKey = "oauth_token_secret";
79
private const string OAuthVerifierKey = "oauth_verifier";
81
private const string HMACSHA1SignatureType = "HMAC-SHA1";
82
private const string PlainTextSignatureType = "PLAINTEXT";
83
private const string RSASHA1SignatureType = "RSA-SHA1";
85
private Random random = new Random ();
87
private string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
90
/// Helper function to compute a hash value.
92
/// <param name="hashAlgorithm">
93
/// The hashing algoirhtm used. If that algorithm needs some initialization, like HMAC and its derivatives,
94
/// they should be initialized prior to passing it to this function.
96
/// <param name="data">The data to hash.</param>
97
/// <returns>A Base64 string of the hash value.</returns>
98
private string ComputeHash (HashAlgorithm hashAlgorithm, string data)
100
log.LogDebug ("Computing hash for data {0}", data);
102
if (hashAlgorithm == null) throw new ArgumentNullException ("hashAlgorithm");
103
if (string.IsNullOrEmpty (data)) throw new ArgumentNullException ("data");
105
byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes (data);
106
byte[] hashBytes = hashAlgorithm.ComputeHash (dataBuffer);
108
return Convert.ToBase64String (hashBytes);
112
/// URL encodes a string using OAuth's encoding scheme (slightly different from HttpUtility's UrlEncode).
114
/// <param name="value">The string to URL encode.</param>
115
/// <returns>An URL encoded string.</returns>
116
private string UrlEncode (string value)
118
log.LogDebug ("URL encoding value.");
119
var result = new StringBuilder ();
121
foreach (char symbol in value) {
122
if (unreservedChars.IndexOf(symbol) != -1) result.Append(symbol);
123
else result.Append('%' + String.Format("{0:X2}", (int)symbol));
126
return result.ToString();
130
/// Internal function to cut out all non oauth query string parameters.
132
/// <param name="parameters">The query string part of the URL.</param>
133
/// <returns>A list of QueryParameter each containing the parameter name and value.</returns>
134
private IEnumerable<IQueryParameter<string>> GetQueryParameters (string parameters)
136
log.LogDebug ("Creating list of parameters from parameter string {0}", parameters);
138
return CreateQueryParametersIterator (parameters);
141
private IEnumerable<IQueryParameter<string>> CreateQueryParametersIterator (string parameters)
143
if (parameters == null) throw new ArgumentNullException ("parameters");
144
var parameterDictionary = HttpUtility.ParseQueryString (parameters).ToDictionary ();
146
foreach (var kvp in parameterDictionary)
147
yield return new QueryParameter<string> (kvp.Key, kvp.Value, s => string.IsNullOrEmpty (s));
151
/// Generate the signature base that is used to produce the signature
153
/// <param name="url">The full URL that needs to be signed including its non OAuth URL parameters.</param>
154
/// <param name="consumerKey">The consumer key.</param>
155
/// <param name="token">The token, if available. If not available pass null or an empty string.</param>
156
/// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string.</param>
157
/// <param name="verifier">The callback verifier, if available. If not available pass null or an empty string.</param>
158
/// <param name="httpMethod">The HTTP method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
159
/// <param name="signatureType">The signature type. To use the default values use <see cref="SignatureType">SignatureType</see>.</param>
160
/// <returns>The signature base.</returns>
161
private string GenerateSignatureBase (Uri url, string consumerKey, string token, string tokenSecret, string verifier,
162
RequestMethod method, TimeSpan timeStamp, string nonce, SignatureType signatureType, out string normalizedUrl,
163
out List<IQueryParameter<string>> parameters)
165
log.LogDebug ("Generating signature base for OAuth request.");
167
token = token ?? string.Empty;
168
tokenSecret = tokenSecret ?? string.Empty;
169
verifier = verifier ?? String.Empty;
171
if (consumerKey == null) throw new ArgumentNullException ("consumerKey");
173
log.LogDebug ("URL: {0}", url.Query);
175
var signatureString = string.Empty;
177
switch (signatureType) {
178
case SignatureType.HMACSHA1:
179
signatureString = "HMAC-SHA1";
181
case SignatureType.RSASHA1:
182
signatureString = "RSA-SHA1";
184
case SignatureType.PLAINTEXT:
185
signatureString = SignatureType.PLAINTEXT.ToString ();
189
parameters = GetQueryParameters (url.Query).Concat (new List<IQueryParameter<string>> {
190
new QueryParameter<string> (OAuthVersionKey, OAuthVersion, s => string.IsNullOrEmpty (s)),
191
new QueryParameter<string> (OAuthTimestampKey, ((long)timeStamp.TotalSeconds).ToString (), s => string.IsNullOrEmpty (s)),
192
new QueryParameter<string> (OAuthSignatureMethodKey, signatureString, s => string.IsNullOrEmpty (s)),
193
new QueryParameter<string> (OAuthNonceKey, nonce, s => string.IsNullOrEmpty (s)),
194
new QueryParameter<string> (OAuthConsumerKeyKey, consumerKey, s => string.IsNullOrEmpty (s))
197
if (!string.IsNullOrEmpty (token)) parameters.Add (new QueryParameter<string> (OAuthTokenKey, token, s => string.IsNullOrEmpty (s)));
198
if (!string.IsNullOrEmpty (verifier)) parameters.Add (new QueryParameter<string> (OAuthVerifierKey, verifier, s => string.IsNullOrEmpty (s)));
200
log.LogDebug ("Normalizing URL for signature.");
202
normalizedUrl = string.Format ("{0}://{1}", url.Scheme, url.Host);
203
if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) normalizedUrl += ":" + url.Port;
204
normalizedUrl += url.AbsolutePath;
206
log.LogDebug ("Generated normalized URL: {0}", normalizedUrl);
207
log.LogDebug ("Normalizing request parameters.");
210
string normalizedRequestParameters = parameters.NormalizeRequestParameters ();
212
log.LogDebug ("Normalized request parameters {0}.", normalizedRequestParameters);
213
log.LogDebug ("Generating signature base from normalized URL and request parameters.");
215
var signatureBase = new StringBuilder ();
216
signatureBase.AppendFormat("{0}&", method.ToString ());
217
signatureBase.AppendFormat("{0}&", UrlEncode (normalizedUrl));
218
signatureBase.AppendFormat("{0}", UrlEncode (normalizedRequestParameters));
220
log.LogDebug ("Signature base: {0}", signatureBase.ToString ());
222
return signatureBase.ToString ();
226
/// Generate the signature value based on the given signature base and hash algorithm.
228
/// <param name="signatureBase">
229
/// The signature based as produced by the GenerateSignatureBase method or by any other means.
231
/// <param name="hash">
232
/// The hash algorithm used to perform the hashing. If the hashing algorithm requires
233
/// initialization or a key it should be set prior to calling this method.
235
/// <returns>A Base64 string of the hash value.</returns>
236
private string GenerateSignatureUsingHash (string signatureBase, HashAlgorithm hash)
238
log.LogDebug ("Generating hashed signature.");
239
return ComputeHash (hash, signatureBase);
243
/// Generates a signature using the HMAC-SHA1 algorithm
245
/// <param name="url">The full URL that needs to be signed including its non-OAuth URL parameters.</param>
246
/// <param name="consumerKey">The consumer key.</param>
247
/// <param name="consumerSecret">The consumer seceret.</param>
248
/// <param name="token">The token, if available. If not available pass null or an empty string.</param>
249
/// <param name="tokenSecret">The token secret, if available. If not, pass null or an empty string.</param>
250
/// <param name="verifier">The callback verifier, if available. If not, pass null or an empty string.</param>
251
/// <param name="httpMethod">The HTTP method used. Must be valid HTTP method verb (POST, GET, PUT, etc).</param>
252
/// <returns>A Base64 string of the hash value.</returns>
253
protected string GenerateSignature (Uri url, string consumerKey, string consumerSecret, string token,
254
string tokenSecret, string verifier, RequestMethod method, TimeSpan timeStamp, string nonce, out string normalizedUrl,
255
out List<IQueryParameter<string>> parameters)
257
log.LogDebug ("Generating signature using HMAC-SHA1 algorithm.");
258
return GenerateSignature (url, consumerKey, consumerSecret, token, tokenSecret, verifier, method, timeStamp, nonce,
259
SignatureType.HMACSHA1, out normalizedUrl, out parameters);
263
/// Generates a signature using the specified signature type.
265
/// <param name="url">The full URL that needs to be signed including its non-OAuth URL parameters.</param>
266
/// <param name="consumerKey">The consumer key.</param>
267
/// <param name="consumerSecret">The consumer seceret.</param>
268
/// <param name="token">The token, if available. If not available pass null or an empty string.</param>
269
/// <param name="tokenSecret">The token secret, if available. If not, pass null or an empty string.</param>
270
/// <param name="verifier">The callback verifier, if available. If not, pass null or an empty string.</param>
271
/// <param name="httpMethod">The HTTP method used. Must be a valid HTTP method verb (POST,GET,PUT, etc).</param>
272
/// <param name="signatureType">The type of signature to use.</param>
273
/// <returns>A Base64 string of the hash value.</returns>
274
private string GenerateSignature (Uri url, string consumerKey, string consumerSecret, string token,
275
string tokenSecret, string verifier, RequestMethod method, TimeSpan timeStamp, string nonce, SignatureType signatureType,
276
out string normalizedUrl, out List<IQueryParameter<string>> parameters)
278
log.LogDebug ("Generating signature using signature type {0}", signatureType);
280
normalizedUrl = null;
283
switch (signatureType)
285
case SignatureType.PLAINTEXT:
286
var signature = UrlEncode (string.Format ("{0}&{1}", consumerSecret, tokenSecret));
287
log.LogDebug ("Plaintext encoding signature {0} of consumer secret and token secret.", signature);
289
case SignatureType.HMACSHA1:
290
string signatureBase = GenerateSignatureBase (url, consumerKey, token, tokenSecret, verifier, method,
291
timeStamp, nonce, SignatureType.HMACSHA1, out normalizedUrl, out parameters);
293
var hmacsha1 = new HMACSHA1 ();
294
hmacsha1.Key = Encoding.ASCII.GetBytes (string.Format ("{0}&{1}",
295
UrlEncode (consumerSecret),
296
string.IsNullOrEmpty (tokenSecret) ? "" : UrlEncode(tokenSecret)));
298
var hashedSignature = GenerateSignatureUsingHash (signatureBase, hmacsha1);
300
log.LogDebug ("HMAC-SHA1 encoded signature {0} of consumer secret and token secret.", hashedSignature);
301
return hashedSignature;
302
case SignatureType.RSASHA1:
303
throw new NotImplementedException ();
305
throw new ArgumentException ("Unknown signature type", "signatureType");
310
/// Generate the timestamp for the signature.
312
/// <returns>A string timestamp.</returns>
313
protected TimeSpan GenerateTimeStamp ()
315
log.LogDebug ("Generating time stamp.");
316
// Default implementation of UNIX time of the current UTC time
317
return DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
321
/// Generate a nonce.
323
/// <returns>A random nonce string.</returns>
324
protected virtual string GenerateNonce()
326
log.LogDebug ("Generating nonce.");
327
// Just a simple implementation of a random number between 123400 and 9999999
328
return random.Next (123400, 9999999).ToString ();
b'\\ No newline at end of file'