/// <summary> /// Gets the Headers for HttpSigning /// </summary> /// <param name="method"></param> /// <param name="path"></param> /// <param name="requestOptions"></param> /// <returns></returns> internal Dictionary <string, string> GetHttpSignedHeader(string basePath, string method, string path, RequestOptions requestOptions) { const string HEADER_REQUEST_TARGET = "(request-target)"; //The time when the HTTP signature expires. The API server should reject HTTP requests //that have expired. const string HEADER_EXPIRES = "(expires)"; //The 'Date' header. const string HEADER_DATE = "Date"; //The 'Host' header. const string HEADER_HOST = "Host"; //The time when the HTTP signature was generated. const string HEADER_CREATED = "(created)"; //When the 'Digest' header is included in the HTTP signature, the client automatically //computes the digest of the HTTP request body, per RFC 3230. const string HEADER_DIGEST = "Digest"; //The 'Authorization' header is automatically generated by the client. It includes //the list of signed headers and a base64-encoded signature. const string HEADER_AUTHORIZATION = "Authorization"; //Hash table to store singed headers var HttpSignedRequestHeader = new Dictionary <string, string>(); var HttpSignatureHeader = new Dictionary <string, string>(); if (HttpSigningHeader.Count == 0) { HttpSigningHeader.Add("(created)"); } if (requestOptions.PathParameters != null) { foreach (var pathParam in requestOptions.PathParameters) { var tempPath = path.Replace(pathParam.Key, "0"); path = string.Format(tempPath, pathParam.Value); } } var httpValues = HttpUtility.ParseQueryString(String.Empty); foreach (var parameter in requestOptions.QueryParameters) { if (parameter.Value.Count > 1) { // array foreach (var value in parameter.Value) { httpValues.Add(parameter.Key + "[]", value); } } else { httpValues.Add(parameter.Key, parameter.Value[0]); } } var uriBuilder = new UriBuilder(string.Concat(basePath, path)); uriBuilder.Query = httpValues.ToString(); var dateTime = DateTime.Now; String Digest = String.Empty; //get the body string requestBody = string.Empty; if (requestOptions.Data != null) { var serializerSettings = new JsonSerializerSettings(); serializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); requestBody = JsonConvert.SerializeObject(requestOptions.Data, serializerSettings); } if (HashAlgorithm == HashAlgorithmName.SHA256) { var bodyDigest = GetStringHash(HashAlgorithm.ToString(), requestBody); Digest = string.Format("SHA-256={0}", Convert.ToBase64String(bodyDigest)); } else if (HashAlgorithm == HashAlgorithmName.SHA512) { var bodyDigest = GetStringHash(HashAlgorithm.ToString(), requestBody); Digest = string.Format("SHA-512={0}", Convert.ToBase64String(bodyDigest)); } else { throw new Exception(string.Format("{0} not supported", HashAlgorithm)); } foreach (var header in HttpSigningHeader) { if (header.Equals(HEADER_REQUEST_TARGET)) { var targetUrl = string.Format("{0} {1}{2}", method.ToLower(), uriBuilder.Path, uriBuilder.Query); HttpSignatureHeader.Add(header.ToLower(), targetUrl); } else if (header.Equals(HEADER_EXPIRES)) { var expireDateTime = dateTime.AddSeconds(SignatureValidityPeriod); HttpSignatureHeader.Add(header.ToLower(), GetUnixTime(expireDateTime).ToString()); } else if (header.Equals(HEADER_DATE)) { var utcDateTime = dateTime.ToString("r").ToString(); HttpSignatureHeader.Add(header.ToLower(), utcDateTime); HttpSignedRequestHeader.Add(HEADER_DATE, utcDateTime); } else if (header.Equals(HEADER_HOST)) { HttpSignatureHeader.Add(header.ToLower(), uriBuilder.Host); HttpSignedRequestHeader.Add(HEADER_HOST, uriBuilder.Host); } else if (header.Equals(HEADER_CREATED)) { HttpSignatureHeader.Add(header.ToLower(), GetUnixTime(dateTime).ToString()); } else if (header.Equals(HEADER_DIGEST)) { HttpSignedRequestHeader.Add(HEADER_DIGEST, Digest); HttpSignatureHeader.Add(header.ToLower(), Digest); } else { bool isHeaderFound = false; foreach (var item in requestOptions.HeaderParameters) { if (string.Equals(item.Key, header, StringComparison.OrdinalIgnoreCase)) { HttpSignatureHeader.Add(header.ToLower(), item.Value.ToString()); isHeaderFound = true; break; } } if (!isHeaderFound) { throw new Exception(string.Format("Cannot sign HTTP request.Request does not contain the {0} header.", header)); } } } var headersKeysString = String.Join(" ", HttpSignatureHeader.Keys); var headerValuesList = new List <string>(); foreach (var keyVal in HttpSignatureHeader) { headerValuesList.Add(string.Format("{0}: {1}", keyVal.Key, keyVal.Value)); } //Concatinate headers value separated by new line var headerValuesString = string.Join("\n", headerValuesList); var signatureStringHash = GetStringHash(HashAlgorithm.ToString(), headerValuesString); string headerSignatureStr = null; var keyType = GetKeyType(KeyFilePath); if (keyType == PrivateKeyType.RSA) { headerSignatureStr = GetRSASignature(signatureStringHash); } else if (keyType == PrivateKeyType.ECDSA) { headerSignatureStr = GetECDSASignature(signatureStringHash); } var cryptographicScheme = "hs2019"; var authorizationHeaderValue = string.Format("Signature keyId=\"{0}\",algorithm=\"{1}\"", KeyId, cryptographicScheme); if (HttpSignatureHeader.ContainsKey(HEADER_CREATED)) { authorizationHeaderValue += string.Format(",created={0}", HttpSignatureHeader[HEADER_CREATED]); } if (HttpSignatureHeader.ContainsKey(HEADER_EXPIRES)) { authorizationHeaderValue += string.Format(",expires={0}", HttpSignatureHeader[HEADER_EXPIRES]); } authorizationHeaderValue += string.Format(",headers=\"{0}\",signature=\"{1}\"", headersKeysString, headerSignatureStr); HttpSignedRequestHeader.Add(HEADER_AUTHORIZATION, authorizationHeaderValue); return(HttpSignedRequestHeader); }
internal Dictionary <string, string> GetHttpSignedHeader(System.Net.Http.HttpRequestMessage request, string requestBody, System.Threading.CancellationToken?cancellationToken = null) { if (request.RequestUri == null) { throw new NullReferenceException("The request URI was null"); } const string HEADER_REQUEST_TARGET = "(request-target)"; // The time when the HTTP signature expires. The API server should reject HTTP requests that have expired. const string HEADER_EXPIRES = "(expires)"; //The 'Date' header. const string HEADER_DATE = "Date"; //The 'Host' header. const string HEADER_HOST = "Host"; //The time when the HTTP signature was generated. const string HEADER_CREATED = "(created)"; //When the 'Digest' header is included in the HTTP signature, the client automatically //computes the digest of the HTTP request body, per RFC 3230. const string HEADER_DIGEST = "Digest"; //The 'Authorization' header is automatically generated by the client. It includes //the list of signed headers and a base64-encoded signature. const string HEADER_AUTHORIZATION = "Authorization"; //Hash table to store singed headers var HttpSignedRequestHeader = new Dictionary <string, string>(); var httpSignatureHeader = new Dictionary <string, string?>(); if (HttpSigningHeader.Count == 0) { HttpSigningHeader.Add("(created)"); } var dateTime = DateTime.Now; string digest = String.Empty; if (HashAlgorithm == HashAlgorithmName.SHA256) { var bodyDigest = GetStringHash(HashAlgorithm.ToString(), requestBody); digest = string.Format("SHA-256={0}", Convert.ToBase64String(bodyDigest)); } else if (HashAlgorithm == HashAlgorithmName.SHA512) { var bodyDigest = GetStringHash(HashAlgorithm.ToString(), requestBody); digest = string.Format("SHA-512={0}", Convert.ToBase64String(bodyDigest)); } else { throw new Exception(string.Format("{0} not supported", HashAlgorithm)); } foreach (var header in HttpSigningHeader) { if (header.Equals(HEADER_REQUEST_TARGET)) { httpSignatureHeader.Add(header.ToLower(), request.RequestUri.ToString()); } else if (header.Equals(HEADER_EXPIRES)) { var expireDateTime = dateTime.AddSeconds(SignatureValidityPeriod); httpSignatureHeader.Add(header.ToLower(), GetUnixTime(expireDateTime).ToString()); } else if (header.Equals(HEADER_DATE)) { var utcDateTime = dateTime.ToString("r").ToString(); httpSignatureHeader.Add(header.ToLower(), utcDateTime); HttpSignedRequestHeader.Add(HEADER_DATE, utcDateTime); } else if (header.Equals(HEADER_HOST)) { httpSignatureHeader.Add(header.ToLower(), request.RequestUri.ToString()); HttpSignedRequestHeader.Add(HEADER_HOST, request.RequestUri.ToString()); } else if (header.Equals(HEADER_CREATED)) { httpSignatureHeader.Add(header.ToLower(), GetUnixTime(dateTime).ToString()); } else if (header.Equals(HEADER_DIGEST)) { HttpSignedRequestHeader.Add(HEADER_DIGEST, digest); httpSignatureHeader.Add(header.ToLower(), digest); } else { bool isHeaderFound = false; foreach (var item in request.Headers) { if (string.Equals(item.Key, header, StringComparison.OrdinalIgnoreCase)) { httpSignatureHeader.Add(header.ToLower(), item.Value.ToString()); isHeaderFound = true; break; } } if (!isHeaderFound) { throw new Exception(string.Format("Cannot sign HTTP request.Request does not contain the {0} header.", header)); } } } var headersKeysString = String.Join(" ", httpSignatureHeader.Keys); var headerValuesList = new List <string>(); foreach (var keyVal in httpSignatureHeader) { headerValuesList.Add(string.Format("{0}: {1}", keyVal.Key, keyVal.Value)); } //Concatinate headers value separated by new line var headerValuesString = string.Join("\n", headerValuesList); var signatureStringHash = GetStringHash(HashAlgorithm.ToString(), headerValuesString); string?headerSignatureStr = null; var keyType = GetKeyType(KeyFilePath); if (keyType == PrivateKeyType.RSA) { headerSignatureStr = GetRSASignature(signatureStringHash); } else if (keyType == PrivateKeyType.ECDSA) { headerSignatureStr = GetECDSASignature(signatureStringHash); } var cryptographicScheme = "hs2019"; var authorizationHeaderValue = string.Format("Signature keyId=\"{0}\",algorithm=\"{1}\"", KeyId, cryptographicScheme); if (httpSignatureHeader.ContainsKey(HEADER_CREATED)) { authorizationHeaderValue += string.Format(",created={0}", httpSignatureHeader[HEADER_CREATED]); } if (httpSignatureHeader.ContainsKey(HEADER_EXPIRES)) { authorizationHeaderValue += string.Format(",expires={0}", httpSignatureHeader[HEADER_EXPIRES]); } authorizationHeaderValue += string.Format(",headers=\"{0}\",signature=\"{1}\"", headersKeysString, headerSignatureStr); HttpSignedRequestHeader.Add(HEADER_AUTHORIZATION, authorizationHeaderValue); return(HttpSignedRequestHeader); }