public void TestS3SignerSignatureVersion(SignatureVersion signatureVersion, string clientConfigSignatureVersion, bool awsConfigsS3UseSignatureVersion4, SignatureVersion expectedSignatureVersion) { var originalAWSConfigsS3UseSignatureVersion4 = AWSConfigsS3.UseSignatureVersion4; try { AWSConfigsS3.UseSignatureVersion4 = awsConfigsS3UseSignatureVersion4; var signer = new S3Signer(); var putObjectRequest = new PutObjectRequest(); var iRequest = new DefaultRequest(putObjectRequest, "s3") { SignatureVersion = signatureVersion, Endpoint = new System.Uri("https://does_not_matter.com") }; var config = new AmazonS3Config { SignatureVersion = clientConfigSignatureVersion, RegionEndpoint = RegionEndpoint.USWest1 }; signer.Sign(iRequest, config, new RequestMetrics(), new ImmutableCredentials("ACCESS", "SECRET", "")); Assert.IsTrue(iRequest.Headers.ContainsKey(HeaderKeys.AuthorizationHeader)); if (expectedSignatureVersion == SignatureVersion.SigV4a) { Assert.IsTrue(iRequest.Headers[HeaderKeys.AuthorizationHeader].Contains("AWS4-ECDSA-P256-SHA256")); } else if (expectedSignatureVersion == SignatureVersion.SigV4) { Assert.IsTrue(iRequest.Headers[HeaderKeys.AuthorizationHeader].Contains("AWS4-HMAC-SHA256")); } else if (expectedSignatureVersion == SignatureVersion.SigV2) { Assert.IsTrue(iRequest.Headers[HeaderKeys.AuthorizationHeader].Contains("AWS ACCESS")); } } finally { AWSConfigsS3.UseSignatureVersion4 = originalAWSConfigsS3UseSignatureVersion4; } }
private void ParseAuthorizationHeader() { string logMessage = ""; if (String.IsNullOrEmpty(Authorization)) { return; } string exceptionMsg = "Invalid authorization header format: " + Authorization; try { #region Retrieve-Outer-Values // [encryption] [values] string[] valsOuter = Authorization.Split(new[] { ' ' }, 2); if (valsOuter == null || valsOuter.Length < 2) { throw new ArgumentException(exceptionMsg); } logMessage += _Header + "Authorization header : " + Authorization + Environment.NewLine; logMessage += _Header + "Outer header values :" + Environment.NewLine; for (int i = 0; i < valsOuter.Length; i++) { logMessage += " " + i + ": " + valsOuter[i].Trim() + Environment.NewLine; } #endregion if (valsOuter[0].Equals("AWS")) { #region Signature-V2 // see https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader // Authorization: AWS AWSAccessKeyId:Signature string[] valsInner = valsOuter[1].Split(':'); logMessage += _Header + "Inner header values" + Environment.NewLine; for (int i = 0; i < valsInner.Length; i++) { logMessage += " " + i + ": " + valsInner[i].Trim() + Environment.NewLine; } if (valsInner.Length != 2) { throw new ArgumentException(exceptionMsg); } SignatureVersion = S3SignatureVersion.Version2; AccessKey = valsInner[0].Trim(); Signature = valsInner[1].Trim(); logMessage += _Header + "Signature version : " + SignatureVersion.ToString() + Environment.NewLine + _Header + "Access key : " + AccessKey + Environment.NewLine + _Header + "Signature : " + Signature; return; #endregion } else if (valsOuter[0].Equals("AWS4-HMAC-SHA256")) { #region Signature-V4 // see https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html // // AWS4-HMAC-SHA256 Credential=access/20190418/us-east-1/s3/aws4_request, SignedHeaders=content-length;content-type;host;user-agent;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length, Signature=66946e06895806f4e32d32217c1a02313b9d9235b759f3a690742c8f9971daa0 // // valsOuter[0] AWS4-HMAC-SHA256 // valsOuter[1] everything else... SignatureVersion = S3SignatureVersion.Version4; string[] keyValuePairs = valsOuter[1].Split(','); List <string> keyValuePairsTrimmed = new List <string>(); logMessage += _Header + "Inner header values" + Environment.NewLine; for (int i = 0; i < keyValuePairs.Length; i++) { string currKey = keyValuePairs[i]; if (String.IsNullOrEmpty(currKey)) { continue; } currKey = currKey.Trim(); keyValuePairsTrimmed.Add(currKey); logMessage += i + ": " + keyValuePairs[i].Trim() + Environment.NewLine; } foreach (string currKey in keyValuePairsTrimmed) { if (currKey.StartsWith("Credential=")) { #region Credentials string credentialString = currKey.Replace("Credential=", "").Trim(); string[] credentialVals = credentialString.Split('/'); if (credentialVals.Length < 5) { throw new ArgumentException(exceptionMsg); } AccessKey = credentialVals[0].Trim(); Region = credentialVals[2].Trim(); #endregion } else if (currKey.StartsWith("SignedHeaders=")) { #region Signed-Headers string signedHeadersString = currKey.Replace("SignedHeaders=", "").Trim(); string[] signedHeaderVals = signedHeadersString.Split(';'); if (signedHeaderVals != null && signedHeaderVals.Length > 0) { foreach (string currSignedHeader in signedHeaderVals) { SignedHeaders.Add(currSignedHeader.Trim()); } SignedHeaders.Sort(); } #endregion } else if (currKey.StartsWith("Signature=")) { #region Signature Signature = currKey.Replace("Signature=", "").Trim(); #endregion } else if (currKey.StartsWith("Expires=")) { #region Expires Expires = currKey.Replace("Expires=", "").Trim(); #endregion } } logMessage += _Header + "Signature version : " + SignatureVersion.ToString() + Environment.NewLine + _Header + "Access key : " + AccessKey + Environment.NewLine + _Header + "Region : " + Region + Environment.NewLine + _Header + "Signature : " + Signature; return; #endregion } else { throw new ArgumentException(exceptionMsg + Authorization); } } finally { _Logger?.Invoke(logMessage); } }
private static long GetSecondsUntilExpiration(IClientConfig config, GetPreSignedUrlRequest request, SignatureVersion signatureVersion) { DateTime baselineTime; if (signatureVersion == SignatureVersion.SigV2) { baselineTime = new DateTime(1970, 1, 1); } else // SigV4 or SigV4a { baselineTime = config.CorrectedUtcNow; } return(Convert.ToInt64((request.Expires.ToUniversalTime() - baselineTime).TotalSeconds)); }
/// <summary> /// Marshalls the parameters for a presigned url for a preferred signing protocol. /// </summary> /// <param name="config">service client configuration</param> /// <param name="getPreSignedUrlRequest"></param> /// <param name="accessKey"></param> /// <param name="token"></param> /// <param name="signatureVersion">Signature version to use. /// If AWS4 signing will be used and if the expiry period in the request exceeds the /// maximum allowed for AWS4 (one week), an ArgumentException is thrown. /// </param> /// <returns>Internal request</returns> private static IRequest Marshall(IClientConfig config, GetPreSignedUrlRequest getPreSignedUrlRequest, string accessKey, string token, SignatureVersion signatureVersion) { IRequest request = new DefaultRequest(getPreSignedUrlRequest, "AmazonS3"); request.HttpMethod = getPreSignedUrlRequest.Verb.ToString(); var headers = getPreSignedUrlRequest.Headers; foreach (var key in headers.Keys) { request.Headers[key] = headers[key]; } AmazonS3Util.SetMetadataHeaders(request, getPreSignedUrlRequest.Metadata); if (getPreSignedUrlRequest.ServerSideEncryptionMethod != null && getPreSignedUrlRequest.ServerSideEncryptionMethod != ServerSideEncryptionMethod.None) { request.Headers.Add(HeaderKeys.XAmzServerSideEncryptionHeader, S3Transforms.ToStringValue(getPreSignedUrlRequest.ServerSideEncryptionMethod)); } if (getPreSignedUrlRequest.IsSetServerSideEncryptionCustomerMethod()) { request.Headers.Add(HeaderKeys.XAmzSSECustomerAlgorithmHeader, getPreSignedUrlRequest.ServerSideEncryptionCustomerMethod); } if (getPreSignedUrlRequest.IsSetServerSideEncryptionKeyManagementServiceKeyId()) { request.Headers.Add(HeaderKeys.XAmzServerSideEncryptionAwsKmsKeyIdHeader, getPreSignedUrlRequest.ServerSideEncryptionKeyManagementServiceKeyId); } if (getPreSignedUrlRequest.IsSetRequestPayer() && getPreSignedUrlRequest.RequestPayer == RequestPayer.Requester) { request.Parameters.Add("x-amz-request-payer", RequestPayer.Requester.Value); } var queryParameters = request.Parameters; var uriResourcePath = new StringBuilder("/"); if (!string.IsNullOrEmpty(getPreSignedUrlRequest.BucketName)) { uriResourcePath.Append(S3Transforms.ToStringValue(getPreSignedUrlRequest.BucketName)); } if (!string.IsNullOrEmpty(getPreSignedUrlRequest.Key)) { if (uriResourcePath.Length > 1) { uriResourcePath.Append("/"); } uriResourcePath.Append(S3Transforms.ToStringValue(getPreSignedUrlRequest.Key)); } var expires = GetSecondsUntilExpiration(config, getPreSignedUrlRequest, signatureVersion); if ((signatureVersion == SignatureVersion.SigV4 || signatureVersion == SignatureVersion.SigV4a) && expires > AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry) { var msg = string.Format(CultureInfo.InvariantCulture, "The maximum expiry period for a presigned url using AWS4 signing is {0} seconds", AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry); throw new ArgumentException(msg); } if (signatureVersion == SignatureVersion.SigV2) { queryParameters.Add("Expires", expires.ToString(CultureInfo.InvariantCulture)); queryParameters.Add("AWSAccessKeyId", accessKey); if (!string.IsNullOrEmpty(token)) { queryParameters.Add("x-amz-security-token", token); } } else // SigV4 or SigV4a { queryParameters.Add(HeaderKeys.XAmzExpires, expires.ToString(CultureInfo.InvariantCulture)); if (!string.IsNullOrEmpty(token)) { queryParameters.Add("X-Amz-Security-Token", token); } } if (getPreSignedUrlRequest.IsSetVersionId()) { request.AddSubResource("versionId", S3Transforms.ToStringValue(getPreSignedUrlRequest.VersionId)); } if (getPreSignedUrlRequest.IsSetUploadId()) { request.AddSubResource("uploadId", S3Transforms.ToStringValue(getPreSignedUrlRequest.UploadId)); } if (getPreSignedUrlRequest.IsSetPartNumber()) { request.AddSubResource("partNumber", S3Transforms.ToStringValue(getPreSignedUrlRequest.PartNumber)); } var responseHeaderOverrides = getPreSignedUrlRequest.ResponseHeaderOverrides; if (!string.IsNullOrEmpty(responseHeaderOverrides.CacheControl)) { queryParameters.Add("response-cache-control", responseHeaderOverrides.CacheControl); } if (!string.IsNullOrEmpty(responseHeaderOverrides.ContentType)) { queryParameters.Add("response-content-type", responseHeaderOverrides.ContentType); } if (!string.IsNullOrEmpty(responseHeaderOverrides.ContentLanguage)) { queryParameters.Add("response-content-language", responseHeaderOverrides.ContentLanguage); } if (!string.IsNullOrEmpty(responseHeaderOverrides.Expires)) { queryParameters.Add("response-expires", responseHeaderOverrides.Expires); } if (!string.IsNullOrEmpty(responseHeaderOverrides.ContentDisposition)) { queryParameters.Add("response-content-disposition", responseHeaderOverrides.ContentDisposition); } if (!string.IsNullOrEmpty(responseHeaderOverrides.ContentEncoding)) { queryParameters.Add("response-content-encoding", responseHeaderOverrides.ContentEncoding); } // Add custom parameters to be included and signed foreach (string k in getPreSignedUrlRequest.Parameters.Keys) { queryParameters.Add(k, getPreSignedUrlRequest.Parameters[k]); } request.ResourcePath = uriResourcePath.ToString(); request.UseQueryString = true; return(request); }
private void FormExternalSignature_Load(object sender, EventArgs e) { txtSignature.Text = Signature; txtSignatureVersion.Text = SignatureVersion.ToString(); txtSoftwareCertNumber.Text = SoftwareCertificateNumber.ToString(); }