diff --git a/ShareX.HelpersLib/Helpers/Helpers.cs b/ShareX.HelpersLib/Helpers/Helpers.cs index 6db6deb3e..d94ea0428 100644 --- a/ShareX.HelpersLib/Helpers/Helpers.cs +++ b/ShareX.HelpersLib/Helpers/Helpers.cs @@ -41,6 +41,7 @@ You should have received a copy of the GNU General Public License using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; +using System.Security.Cryptography; using System.Security.Principal; using System.Text; using System.Text.RegularExpressions; @@ -1165,5 +1166,51 @@ public static string EscapeCLIText(string text) { return string.Format("\"{0}\"", text.Replace("\\", "\\\\").Replace("\"", "\\\"")); } + + public static string BytesToHex(byte[] bytes) + { + StringBuilder sb = new StringBuilder(); + foreach (byte x in bytes) + { + sb.Append(string.Format("{0:x2}", x)); + } + return sb.ToString(); + } + + public static byte[] ComputeSHA256(byte[] data) + { + using (SHA256Managed hashAlgorithm = new SHA256Managed()) + { + return hashAlgorithm.ComputeHash(data); + } + } + + public static byte[] ComputeSHA256(string data) + { + return ComputeSHA256(Encoding.UTF8.GetBytes(data)); + } + + public static byte[] ComputeHMACSHA256(byte[] data, byte[] key) + { + using (HMACSHA256 hashAlgorithm = new HMACSHA256(key)) + { + return hashAlgorithm.ComputeHash(data); + } + } + + public static byte[] ComputeHMACSHA256(string data, string key) + { + return ComputeHMACSHA256(Encoding.UTF8.GetBytes(data), Encoding.UTF8.GetBytes(key)); + } + + public static byte[] ComputeHMACSHA256(byte[] data, string key) + { + return ComputeHMACSHA256(data, Encoding.UTF8.GetBytes(key)); + } + + public static byte[] ComputeHMACSHA256(string data, byte[] key) + { + return ComputeHMACSHA256(Encoding.UTF8.GetBytes(data), key); + } } } \ No newline at end of file diff --git a/ShareX.HelpersLib/Helpers/URLHelpers.cs b/ShareX.HelpersLib/Helpers/URLHelpers.cs index fc1baddfd..0cc5a67f7 100644 --- a/ShareX.HelpersLib/Helpers/URLHelpers.cs +++ b/ShareX.HelpersLib/Helpers/URLHelpers.cs @@ -386,5 +386,27 @@ public static string GetShortURL(string url) return url; } + + public static string CreateQuery(string url, Dictionary args) + { + string query = CreateQuery(args); + + if (!string.IsNullOrEmpty(query)) + { + return url + "?" + query; + } + + return url; + } + + public static string CreateQuery(Dictionary args) + { + if (args != null && args.Count > 0) + { + return string.Join("&", args.Select(x => x.Key + "=" + URLEncode(x.Value)).ToArray()); + } + + return ""; + } } } \ No newline at end of file diff --git a/ShareX.UploadersLib/FileUploaders/AmazonS3.cs b/ShareX.UploadersLib/FileUploaders/AmazonS3.cs index aed1508b9..26357e38d 100644 --- a/ShareX.UploadersLib/FileUploaders/AmazonS3.cs +++ b/ShareX.UploadersLib/FileUploaders/AmazonS3.cs @@ -32,8 +32,6 @@ You should have received a copy of the GNU General Public License using System.Globalization; using System.IO; using System.Linq; -using System.Security.Cryptography; -using System.Text; using System.Windows.Forms; namespace ShareX.UploadersLib.FileUploaders @@ -121,7 +119,7 @@ public override UploadResult Upload(Stream stream, string fileName) string canonicalURI = URLHelpers.AddSlash(uploadPath, SlashType.Prefix); canonicalURI = URLHelpers.URLPathEncode(canonicalURI); - string canonicalQueryString = CreateQueryString(args); + string canonicalQueryString = URLHelpers.CreateQuery(args); string canonicalHeaders = CreateCanonicalHeaders(headers); string canonicalRequest = "PUT" + "\n" + @@ -134,20 +132,21 @@ public override UploadResult Upload(Stream stream, string fileName) string stringToSign = algorithm + "\n" + longDate + "\n" + scope + "\n" + - BytesToHex(ComputeHash(canonicalRequest)); + Helpers.BytesToHex(Helpers.ComputeSHA256(canonicalRequest)); - byte[] dateKey = ComputeHMAC(credentialDate, "AWS4" + Settings.SecretAccessKey); - byte[] dateRegionKey = ComputeHMAC(identifier, dateKey); - byte[] dateRegionServiceKey = ComputeHMAC("s3", dateRegionKey); - byte[] signingKey = ComputeHMAC("aws4_request", dateRegionServiceKey); - string signature = BytesToHex(ComputeHMAC(stringToSign, signingKey)); + byte[] dateKey = Helpers.ComputeHMACSHA256(credentialDate, "AWS4" + Settings.SecretAccessKey); + byte[] dateRegionKey = Helpers.ComputeHMACSHA256(identifier, dateKey); + byte[] dateRegionServiceKey = Helpers.ComputeHMACSHA256("s3", dateRegionKey); + byte[] signingKey = Helpers.ComputeHMACSHA256("aws4_request", dateRegionServiceKey); + string signature = Helpers.BytesToHex(Helpers.ComputeHMACSHA256(stringToSign, signingKey)); args.Add("X-Amz-Signature", signature); headers.Remove("content-type"); headers.Remove("host"); - string url = URLHelpers.CombineURL(host, canonicalURI) + "?" + CreateQueryString(args); + string url = URLHelpers.CombineURL(host, canonicalURI); + url = URLHelpers.CreateQuery(url, args); url = URLHelpers.ForcePrefix(url, "https://"); NameValueCollection responseHeaders = SendRequestGetHeaders(HttpMethod.PUT, url, stream, contentType, null, headers); @@ -228,61 +227,5 @@ private string GetSignedHeaders(NameValueCollection headers) { return string.Join(";", headers.AllKeys.Select(x => x.ToLowerInvariant())); } - - private byte[] ComputeHash(byte[] data) - { - using (SHA256Managed hashAlgorithm = new SHA256Managed()) - { - return hashAlgorithm.ComputeHash(data); - } - } - - private byte[] ComputeHash(string data) - { - return ComputeHash(Encoding.UTF8.GetBytes(data)); - } - - private byte[] ComputeHMAC(byte[] data, byte[] key) - { - using (HMACSHA256 hashAlgorithm = new HMACSHA256(key)) - { - return hashAlgorithm.ComputeHash(data); - } - } - - private byte[] ComputeHMAC(string data, string key) - { - return ComputeHMAC(Encoding.UTF8.GetBytes(data), Encoding.UTF8.GetBytes(key)); - } - - private byte[] ComputeHMAC(byte[] data, string key) - { - return ComputeHMAC(data, Encoding.UTF8.GetBytes(key)); - } - - private byte[] ComputeHMAC(string data, byte[] key) - { - return ComputeHMAC(Encoding.UTF8.GetBytes(data), key); - } - - private string BytesToHex(byte[] bytes) - { - StringBuilder sb = new StringBuilder(); - foreach (byte x in bytes) - { - sb.Append(string.Format("{0:x2}", x)); - } - return sb.ToString(); - } - - private string CreateQueryString(Dictionary args) - { - if (args != null && args.Count > 0) - { - return string.Join("&", args.Select(x => x.Key + "=" + URLHelpers.URLEncode(x.Value)).ToArray()); - } - - return ""; - } } } \ No newline at end of file diff --git a/ShareX.UploadersLib/FileUploaders/AzureStorage.cs b/ShareX.UploadersLib/FileUploaders/AzureStorage.cs index 480f57c26..98f6adecb 100644 --- a/ShareX.UploadersLib/FileUploaders/AzureStorage.cs +++ b/ShareX.UploadersLib/FileUploaders/AzureStorage.cs @@ -59,7 +59,7 @@ public override GenericUploader CreateUploader(UploadersConfig config, TaskRefer public sealed class AzureStorage : FileUploader { - private const string apiVersion = "2016-05-31"; + private const string APIVersion = "2016-05-31"; public string AzureStorageAccountName { get; private set; } public string AzureStorageAccountAccessKey { get; private set; } @@ -91,10 +91,10 @@ public override UploadResult Upload(Stream stream, string fileName) NameValueCollection requestHeaders = new NameValueCollection(); requestHeaders["x-ms-date"] = date; - requestHeaders["x-ms-version"] = apiVersion; + requestHeaders["x-ms-version"] = APIVersion; requestHeaders["x-ms-blob-type"] = "BlockBlob"; - string canonicalizedHeaders = $"x-ms-blob-type:BlockBlob\nx-ms-date:{date}\nx-ms-version:{apiVersion}\n"; + string canonicalizedHeaders = $"x-ms-blob-type:BlockBlob\nx-ms-date:{date}\nx-ms-version:{APIVersion}\n"; string canonicalizedResource = $"/{AzureStorageAccountName}/{AzureStorageContainer}/{fileName}"; string stringToSign = GenerateStringToSign(canonicalizedHeaders, canonicalizedResource, stream.Length.ToString(), contentType); @@ -121,9 +121,9 @@ private void CreateContainerIfNotExists() NameValueCollection requestHeaders = new NameValueCollection(); requestHeaders["Content-Length"] = "0"; requestHeaders["x-ms-date"] = date; - requestHeaders["x-ms-version"] = apiVersion; + requestHeaders["x-ms-version"] = APIVersion; - string canonicalizedHeaders = $"x-ms-date:{date}\nx-ms-version:{apiVersion}\n"; + string canonicalizedHeaders = $"x-ms-date:{date}\nx-ms-version:{APIVersion}\n"; string canonicalizedResource = $"/{AzureStorageAccountName}/{AzureStorageContainer}\nrestype:container"; string stringToSign = GenerateStringToSign(canonicalizedHeaders, canonicalizedResource); @@ -154,15 +154,15 @@ private void CreateContainerIfNotExists() private void SetContainerACL() { string date = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture); - string url = "https://{azureStorageAccountName}.blob.core.windows.net/{azureStorageContainer}?restype=container&comp=acl"; + string url = $"https://{AzureStorageAccountName}.blob.core.windows.net/{AzureStorageContainer}?restype=container&comp=acl"; NameValueCollection requestHeaders = new NameValueCollection(); requestHeaders["Content-Length"] = "0"; requestHeaders["x-ms-date"] = date; - requestHeaders["x-ms-version"] = apiVersion; + requestHeaders["x-ms-version"] = APIVersion; requestHeaders["x-ms-blob-public-access"] = "container"; - string canonicalizedHeaders = $"x-ms-blob-public-access:container\nx-ms-date:{date}\nx-ms-version:{apiVersion}\n"; + string canonicalizedHeaders = $"x-ms-blob-public-access:container\nx-ms-date:{date}\nx-ms-version:{APIVersion}\n"; string canonicalizedResource = $"/{AzureStorageAccountName}/{AzureStorageContainer}\ncomp:acl\nrestype:container"; string stringToSign = GenerateStringToSign(canonicalizedHeaders, canonicalizedResource); diff --git a/ShareX.UploadersLib/FileUploaders/AzureStorageSettings.cs b/ShareX.UploadersLib/FileUploaders/AzureStorageSettings.cs deleted file mode 100644 index 7895fb5dd..000000000 --- a/ShareX.UploadersLib/FileUploaders/AzureStorageSettings.cs +++ /dev/null @@ -1,39 +0,0 @@ -#region License Information (GPL v3) - -/* - ShareX - A program that allows you to take screenshots and share any file type - Copyright (c) 2007-2017 ShareX Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - Optionally you can also view the license at . -*/ - -#endregion License Information (GPL v3) - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ShareX.UploadersLib.FileUploaders -{ - public class AzureStorageSettings - { - public string AccountName { get; set; } - public string AccessKey { get; set; } - public string Container { get; set; } - } -} \ No newline at end of file