using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
/// <summary>
/// CosSignature 的摘要说明 生成腾讯云COS签名类
/// ======作者:rovedog
/// ======日期:2020.2.24
/// </summary>
public class CosSignature
{
/// <summary>
/// 密码ID
/// </summary>
public string SecretId { get; set; }
/// <summary>
/// 密码内容
/// </summary>
public string SecretKey { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime StartTimestamp { get; set; } = DateTime.Now;
/// <summary>
/// 签名有效期,单位秒,默认10分钟
/// </summary>
public int ExpiredTime { get; set; } = 600;
/// <summary>
/// 请求参数
/// </summary>
public NameValueCollection NVC;
/// <summary>
/// 请求头
/// </summary>
public WebHeaderCollection RequestHeader;
/// <summary>
/// 请求方法
/// </summary>
public string HttpMethod { get; set; } = "get";
/// <summary>
/// 请求的url
/// 若需验证url参数则填写,key小写,value需要进行URLEncode,多个key以字典排序,如:max-keys=20&prefix=abc
/// </summary>
///<example>签名中的请求路径以 / 开头,无需URLEncode,如:/ 、 /a/b 或 /测试.jpg</example>
public string HttpURI { get; set; }
/// <summary>
/// 实例初始化对象
/// </summary>
/// <param name="secretId"></param>
/// <param name="secretKey"></param>
/// <param name="HttpUri"></param>
public CosSignature(string secretId, string secretKey, string HttpUri = "/")
{
HttpURI = HttpUri;
SecretId = secretId;
SecretKey = secretKey;
}
/// <summary>
/// 创建一个签名
/// </summary>
/// <returns></returns>
public Return Create()
{
Return R = new Return();
HttpMethod = HttpMethod.ToLower();
List<string> M = new List<string> {"get", "post", "put", "delete", "head"};
if (M.IndexOf(HttpMethod) == -1)
{
R.BOOL = false;
R.Error = "未知请求方法!";
return R;
}
if (string.IsNullOrEmpty(SecretId))
{
R.BOOL = false;
R.Error = "密码ID为空!";
return R;
}
if (string.IsNullOrEmpty(SecretKey))
{
R.BOOL = false;
R.Error = "密码内容为空!";
return R;
}
if (StartTimestamp > DateTime.Now) StartTimestamp = DateTime.Now;
//步骤1:生成 KeyTime
long startTimestamp = (StartTimestamp.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
long endTimestamp = startTimestamp + ExpiredTime;
string keyTime = string.Format("{0};{1}", startTimestamp, endTimestamp);
//步骤2:生成 SignKey
string SignKey = HMACSHA1(SecretKey, keyTime);
//步骤3:生成 UrlParamList 和 HttpParameters
List<string> Key = new List<string>();
List<string> KeyValue = new List<string>();
Dictionary<string, string> Param = new Dictionary<string, string>();
if (NVC != null)
{
foreach (var k in NVC.Keys)
{
string kk = HttpUtility.UrlEncode(k.ToString()).ToLower();
Param.Add(kk, HttpUtility.UrlEncode(NVC[k.ToString()]));
Key.Add(kk);
}
Key.Sort();
foreach (var k in Key)
{
KeyValue.Add(string.Format("{0}={1}", k, Param[k]));
}
}
string HttpParameters = NVC != null ? string.Join("&", KeyValue.ToArray()) : "";
string UrlParamList = NVC != null ? string.Join(";", Key) : "";
//步骤4:生成 HeaderList 和 HttpHeaders
Key.Clear();
Dictionary<string, string> Hearder = new Dictionary<string, string>();
if (RequestHeader != null)
{
foreach (var k in RequestHeader.AllKeys)
{
string kk = HttpUtility.UrlEncode(k).ToLower();
Hearder.Add(kk, HttpUtility.UrlEncode(RequestHeader[k]));
Key.Add(kk);
}
Key.Sort();
KeyValue.Clear();
foreach (var k in Key)
{
KeyValue.Add(string.Format("{0}={1}", k, Hearder[k]));
}
}
string HttpHeaders = RequestHeader != null ? string.Join("&", KeyValue.ToArray()) : "";
string HeaderList = RequestHeader != null ? string.Join(";", Key) : "";
//步骤5:生成 HttpString
string HttpString = string.Format("{0}\n{1}\n{2}\n{3}\n", HttpMethod, HttpURI, HttpParameters, HttpHeaders);
//步骤6:生成 StringToSign
string StringToSign = string.Format("sha1\n{0}\n{1}\n", keyTime, SHA1(HttpString));
//步骤7:生成 Signature
string Signature = HMACSHA1(SignKey, StringToSign);
//步骤8:生成签名
R.STRING = string.Format("q-sign-algorithm=sha1&q-ak={0}&q-sign-time={1}&q-key-time={1}&q-header-list={2}&q-url-param-list={3}&q-signature={4}", SecretId, keyTime, HeaderList, UrlParamList, Signature);
//List<string> o = new List<string> {string.Format("SignKey={0}", SignKey), string.Format("HttpString={0}", HttpString), string.Format("StringToSign={0}", StringToSign)};
//R.OBJECT = string.Join("<br/>", o);
return R;
}
/// <summary>
/// HMACSHA1加密方法
/// </summary>
/// <param name="content"></param>
/// <param name="secretKey"></param>
/// <returns></returns>
public static string HMACSHA1(string secretKey, string content)
{
byte[] keyByte = Encoding.Default.GetBytes(secretKey);
HMACSHA1 hmacsha1 = new HMACSHA1(keyByte);
byte[] messageBytes = Encoding.Default.GetBytes(content);
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
StringBuilder sb = new StringBuilder("");
foreach (byte b in hashmessage)
{
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString();
}
/// <summary>
/// SHA1加密方法
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
public static string SHA1(string content)
{
var sha1 = new SHA1CryptoServiceProvider();
byte[] c = Encoding.Default.GetBytes(content);
byte[] sc = sha1.ComputeHash(c);
StringBuilder sb = new StringBuilder("");
foreach (byte b in sc)
{
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString();
}
}
/// <summary>
/// 需要多个返值的值类型 2019.4.10
/// </summary>
[Serializable]
public class Return
{
public Return()
{
BOOL = true;
INT = 0;
STRING = "";
Error = "";
Information = "";
ExcuteTime = 0;
}
/// <summary>
/// 布尔型返回结果,默认是true
/// </summary>
public bool BOOL { get; set; }
/// <summary>
/// 整型返回结果
/// </summary>
public int INT { get; set; }
/// <summary>
/// 字符串类型结果返回
/// </summary>
public string STRING { get; set; }
/// <summary>
/// 可序列化的object类型返回结果
/// </summary>
public object OBJECT { get; set; }
/// <summary>
/// 执行的相关信息
/// </summary>
public string Information { get; set; }
/// <summary>
/// 错误消息
/// </summary>
public string Error { get; set; }
/// <summary>
/// 执行时间
/// </summary>
public long ExcuteTime { get; set; }
}