Created
May 22, 2011 20:11
-
-
Save chrisntr/985841 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Net; | |
using System.Security.Cryptography; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Text; | |
using System.Text.RegularExpressions; | |
namespace RavelryNet | |
{ | |
public class RavelryClient | |
{ | |
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy | |
{ | |
public TrustAllCertificatePolicy() | |
{ } | |
public bool CheckValidationResult(ServicePoint sp, | |
X509Certificate cert, WebRequest req, int problem) | |
{ | |
return true; | |
} | |
} | |
private readonly string _accessKey, _apiServer, _secretKey; | |
private string _authToken, _signingKey; | |
private WebClient _webClient; | |
public bool Authenticated { get { return _authToken != null; } } | |
public RavelryClient(string accessKey, string secretKey) | |
{ | |
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy(); | |
_accessKey = accessKey; | |
_secretKey = secretKey; | |
_apiServer = "api.ravelry.com"; | |
} | |
public RavelryClient(string accessKey, string secretKey, string apiServer) | |
{ | |
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy(); | |
_accessKey = accessKey; | |
_secretKey = secretKey; | |
_apiServer = apiServer; | |
} | |
public string Get(string uri, Dictionary<String, String> parameters) | |
{ | |
return Request("Get", uri, parameters, null); | |
} | |
private string Request(string method, string url, Dictionary<String, String> parameters, Dictionary<String, String> options) | |
{ | |
var protocol = (options != null && options.ContainsKey("ssl")) ? "https" : "http"; | |
var timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd\\THH:mm:ss.000Z"); | |
var defaults = new Dictionary<String, String> {{"timestamp", timestamp}, {"access_key", _accessKey}}; | |
if(Authenticated) | |
defaults.Add("auth_token", _authToken); | |
parameters = (parameters != null) ? defaults.Union(parameters).ToDictionary(i => i.Key, i => i.Value) : defaults; | |
var sortedParameters = parameters.OrderBy(x => x.Key.ToString()); | |
var queryString = String.Join("&", sortedParameters.Select(x => String.Format("{0}={1}", x.Key, UrlEncodeUpperCase(x.Value))).ToArray()); | |
Console.WriteLine("Query String = {0}", queryString); | |
var signature = Sign(String.Format("http://{0}{1}?{2}", _apiServer, url, queryString)); | |
var signedQueryString = String.Format("{0}&signature={1}", queryString, | |
UrlEncodeUpperCase(signature)); | |
_webClient = new WebClient(); | |
var uri = new Uri(String.Format("{0}://{1}{2}?{3}", protocol, _apiServer, url, signedQueryString)); | |
var completeUrl = String.Format("{0}://{1}{2}?{3}", protocol, _apiServer, url, signedQueryString); | |
var response = _webClient.DownloadString(completeUrl); | |
return response.ToString(); | |
// response = if method == :get | |
// http = Net::HTTP.new(url.host, url.port) | |
// http.use_ssl = protocol == "https" | |
// http.request(Net::HTTP::Get.new(url.request_uri)) | |
// else | |
// raise ApiError, "#{method} method not supported" | |
// end | |
// if response.code == "200" | |
// JSON.parse(response.body) | |
// else | |
// raise ApiError, "#{response.code} #{response.message} : #{response.body}" | |
// end | |
} | |
public void Authenticate(string username, string password) | |
{ | |
var credentials = EncryptAes(String.Format("{0}:{1}", username, password)); | |
var parameters = new Dictionary<String, String> {{"credentials", credentials}}; | |
var options = new Dictionary<String, String> {{"ssl", "true"}}; | |
var result = Request("Get", "/authenticate.json", parameters, options); | |
var json = System.Json.JsonObject.Parse(result); | |
_authToken = json["auth_token"].ToString(); | |
_signingKey = json["signing_key"].ToString(); | |
var what = result.ToString(); | |
//@auth_token = result["auth_token"] | |
//@signing_key = result["signing_key"] | |
} | |
private string EncryptAes(string s) | |
{ | |
var iv = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
var key = Sha256Hash(_secretKey); | |
String result; | |
var rijn = new RijndaelManaged | |
{ | |
Mode = CipherMode.CBC, | |
Padding = PaddingMode.PKCS7 | |
}; | |
using (var msEncrypt = new MemoryStream()) | |
{ | |
using (var encryptor = rijn.CreateEncryptor(key, iv)) | |
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) | |
using (var swEncrypt = new StreamWriter(csEncrypt)) | |
swEncrypt.Write(s); | |
result = Convert.ToBase64String(msEncrypt.ToArray()); | |
} | |
rijn.Clear(); | |
return result; | |
} | |
public static byte[] Sha256Hash(string data) | |
{ | |
var sha = new SHA256Managed(); | |
return sha.ComputeHash(Encoding.UTF8.GetBytes(data)); | |
} | |
private string Sign(string data) | |
{ | |
var key = this.Authenticated ? _signingKey : _secretKey; | |
var encoding = new UTF8Encoding(); | |
var hmacsha256 = new HMACSHA256(encoding.GetBytes(key)); | |
var signature = hmacsha256.ComputeHash(encoding.GetBytes(data)); | |
return Convert.ToBase64String(signature); | |
} | |
static string UrlEncodeUpperCase(string value) | |
{ | |
value = HttpUtility.UrlEncode(value); | |
return Regex.Replace(value, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment