using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using static System.Net.WebRequestMethods; namespace Vinno.vCloud.XunFeiAudio { public class SkyNetAuth { //编码,使用UTF8 private static Encoding CHARSET_UTF8 = Encoding.UTF8; //加密 private static string DIGEST_NAME = "SHA-256"; private static string AUTH_KEY = "Authorization"; public static string generateAuthUrl(String apiKey, String apiSecret, String url) { AuthorizationData authorizationData = assemble(Http.Get, url, apiKey, apiSecret, null, null); string authBase = Convert.ToBase64String(CHARSET_UTF8.GetBytes(authorizationData.Authorization)); authBase = string.Format("{0}?{1}={2}&host={3}&date={4}", url, AUTH_KEY.ToLower(), UrlEncode(authBase, Encoding.UTF8), UrlEncode(authorizationData.Host, Encoding.UTF8), UrlEncode(authorizationData.Date, Encoding.UTF8)); return authBase; } public static string generateAuthUrl(String apiKey, String apiSecret, String url, string body, String apiKeyKey) { AuthorizationData authorizationData = assemble(Http.Get, url, apiKey, apiSecret, body, apiKeyKey); string authBase = Convert.ToBase64String(CHARSET_UTF8.GetBytes(authorizationData.Authorization)); authBase = string.Format("{0}?{1}={2}&host={3}&date={4}", url, AUTH_KEY.ToLower(), UrlEncode(authBase, Encoding.UTF8), UrlEncode(authorizationData.Host, Encoding.UTF8), UrlEncode(authorizationData.Date, Encoding.UTF8)); return authBase; } private static AuthorizationData assemble(string httpMethod, string requestUrl, string apiKey, string apiSecret, string body, string apiKeyKey) { if (string.IsNullOrEmpty(requestUrl)) { throw new Exception("requestUr is empty."); } if (string.IsNullOrEmpty(apiKey)) { throw new Exception("apiKey is empty."); } if (string.IsNullOrEmpty(apiSecret)) { throw new Exception("apiSecret is empty."); } string httpRequestUrl = requestUrl.Replace("ws://", "http://").Replace("wss://", "https://"); Uri uri = new Uri(httpRequestUrl); string dateStr = DateTime.UtcNow.GetDateTimeFormats('r')[0].ToString(); string sha = getSignature(uri.Host, dateStr, getRequestLine(httpMethod, uri.AbsolutePath), apiSecret); string digest = null; if (!string.IsNullOrEmpty(body)) { digest = signBody(body); } apiKeyKey = string.IsNullOrEmpty(apiKeyKey) ? "hmac api_key" : apiKeyKey; string authorization = string.Format("{0}=\"{1}\", algorithm=\"hmac-sha256\", headers=\"host date request-line{2}\", signature=\"{3}\"", apiKeyKey, apiKey, string.IsNullOrEmpty(digest) ? "" : " digest", sha); AuthorizationData authorizationData = new AuthorizationData(); authorizationData.Date = dateStr; authorizationData.Host = uri.Host; authorizationData.Authorization = authorization; authorizationData.Digest = digest; return authorizationData; } private static string getRequestLine(string method, string path) { return string.Format("{0} {1} HTTP/1.1", method.ToUpper(), path); } private static string signBody(String body) { if (string.IsNullOrEmpty(body)) { throw new Exception("body is empty."); } return signBody(CHARSET_UTF8.GetBytes(body)); } private static string signBody(byte[] body) { if (null == body || body.Length == 0) { throw new Exception("body is empty."); } var sha256 = new SHA256Managed(); byte[] hashmessage = sha256.ComputeHash(body); return Convert.ToBase64String(hashmessage); } private static string getSignature(string host, string date, string requestLine, string apiSecret) { if (string.IsNullOrEmpty(host)) { throw new Exception("host is empty."); } if (string.IsNullOrEmpty(date)) { throw new Exception("date is empty."); } if (string.IsNullOrEmpty(requestLine)) { throw new Exception("requestLine is empty."); } if (string.IsNullOrEmpty(apiSecret)) { throw new Exception("apiSecret is empty."); } StringBuilder builder = new StringBuilder("host: ").Append(host).Append("\n").Append("date: ").Append(date).Append("\n").Append(requestLine); byte[] keyByte = CHARSET_UTF8.GetBytes(apiSecret); byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(builder.ToString()); using (var hmacsha256 = new HMACSHA256(keyByte)) { byte[] hashmessage = hmacsha256.ComputeHash(messageBytes); return Convert.ToBase64String(hashmessage); } } private static string UrlEncode(string str, Encoding encoding) { StringBuilder sb = new StringBuilder(); byte[] byStr = encoding.GetBytes(str); for (int i = 0; i < byStr.Length; i++) { sb.Append(@"%" + Convert.ToString(byStr[i], 16)); } return (sb.ToString()); } class AuthorizationData { public string Date { get; set; } public string Host { get; set; } public string Authorization { get; set; } public string Digest { get; set; } public Dictionary GetHeader() { Dictionary headers = new Dictionary(); headers.Add("Host", Host); headers.Add("Date", Date); if (!string.IsNullOrEmpty(Digest)) { headers.Add("Digest", string.Format("%s=%s", DIGEST_NAME, Digest)); } headers.Add(AUTH_KEY, Authorization); return headers; } } } }