From 438d70250064c5fb3cf8ac500f633774e6bcab0c Mon Sep 17 00:00:00 2001 From: Renato Golia Date: Thu, 11 Feb 2021 11:09:22 +0100 Subject: [PATCH] Add possibility to specify encoding when hashing strings (#5) --- appveyor.yml | 9 ++++ src/StringExtensions/HashStringExtensions.cs | 29 ++++++++++-- tests/Tests.Clock/SystemClockTests.cs | 4 +- .../HashStringExtensionsTests.cs | 46 +++++++++++++++++-- 4 files changed, 77 insertions(+), 11 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f1a37bf..25c3e97 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -45,3 +45,12 @@ deploy: - master - main appveyor_repo_tag: true + - provider: GitHub + on: + branch: + - master + - main + appveyor_repo_tag: true + auth_token: + secure: Qv4tMB9BvNni2+v69vK38jQq2ga1+GiI/YqCWkiA1fZN72v2NtaZo6UpwmXQNkop + artifact: /.*.nupkg/ diff --git a/src/StringExtensions/HashStringExtensions.cs b/src/StringExtensions/HashStringExtensions.cs index a7e0c5a..fe9a001 100644 --- a/src/StringExtensions/HashStringExtensions.cs +++ b/src/StringExtensions/HashStringExtensions.cs @@ -14,18 +14,21 @@ public static class HashStringExtensions /// Calculates an hashed representation of using the given and the . /// /// The to hash. + /// The used to read the string. /// An instance of used to calculate the hash . /// The format string used to convert each byte into a string. Default is x2. /// The hash of input string. - public static string Hash(this string input, HashAlgorithm algorithm, string byteFormat = "x2") + public static string Hash(this string input, Encoding encoding, HashAlgorithm algorithm, string byteFormat = "x2") { _ = input ?? throw new ArgumentNullException(nameof(input)); + _ = encoding ?? throw new ArgumentNullException(nameof(encoding)); + _ = algorithm ?? throw new ArgumentNullException(nameof(algorithm)); _ = byteFormat ?? throw new ArgumentNullException(nameof(byteFormat)); - var inputBytes = Encoding.UTF8.GetBytes(input); + var inputBytes = encoding.GetBytes(input); var hashBytes = algorithm.ComputeHash(inputBytes); @@ -39,19 +42,37 @@ public static string Hash(this string input, HashAlgorithm algorithm, string byt return sb.ToString(); } + /// + /// Calculates an hashed representation of using the given and the . The string will be interpreted using . + /// + /// The to hash. + /// An instance of used to calculate the hash . + /// The format string used to convert each byte into a string. Default is x2. + /// The hash of input string. + public static string Hash(this string input, HashAlgorithm algorithm, string byteFormat = "x2") => Hash(input, Encoding.UTF8, algorithm, byteFormat); + /// /// Calculates an hashed representation of using MD5 and the . /// /// The to hash. + /// The used to read the string. /// The format string used to convert each byte into a string. Default is x2. /// The MD5 hash of input string. - public static string MD5(this string input, string byteFormat = "x2") + public static string MD5(this string input, Encoding encoding, string byteFormat = "x2") { #pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms using var hasher = System.Security.Cryptography.MD5.Create(); #pragma warning restore CA5351 // Do Not Use Broken Cryptographic Algorithms - return Hash(input, hasher, byteFormat); + return Hash(input, encoding, hasher, byteFormat); } + + /// + /// Calculates an hashed representation of using MD5 and the . The string will be interpreted using . + /// + /// The to hash. + /// The format string used to convert each byte into a string. Default is x2. + /// The MD5 hash of input string. + public static string MD5(this string input, string byteFormat = "x2") => MD5(input, Encoding.UTF8, byteFormat); } } diff --git a/tests/Tests.Clock/SystemClockTests.cs b/tests/Tests.Clock/SystemClockTests.cs index 739a450..5aa8866 100644 --- a/tests/Tests.Clock/SystemClockTests.cs +++ b/tests/Tests.Clock/SystemClockTests.cs @@ -11,7 +11,7 @@ public class SystemClockTests [Test, AutoData] public void UtcNow_returns_current_time() { - Assert.That(SystemClock.Instance.UtcNow, Is.EqualTo(DateTimeOffset.UtcNow).Within(TimeSpan.FromTicks(100))); + Assert.That(SystemClock.Instance.UtcNow, Is.EqualTo(DateTimeOffset.UtcNow).Within(TimeSpan.FromSeconds(1))); } } -} \ No newline at end of file +} diff --git a/tests/Tests.StringExtensions/HashStringExtensionsTests.cs b/tests/Tests.StringExtensions/HashStringExtensionsTests.cs index 0bbf6e5..b837d4b 100644 --- a/tests/Tests.StringExtensions/HashStringExtensionsTests.cs +++ b/tests/Tests.StringExtensions/HashStringExtensionsTests.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using System.Collections.Generic; using System.Security.Cryptography; +using System.Text; namespace Tests { @@ -11,22 +12,41 @@ public class HashStringExtensionsTests { [Test] [TestCaseSource(nameof(GetAlgorithms))] - public void Hash_returns_correct_hash(HashAlgorithm algorithm, string expected) + public void Hash_returns_correct_hash_with_specified_encoding(string input, HashAlgorithm algorithm, string expected) { - var result = "Hello world".Hash(algorithm); + var result = input.Hash(Encoding.UTF8, algorithm); + + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + [TestCaseSource(nameof(GetAlgorithms))] + public void Hash_returns_correct_hash_with_default_encoding(string input, HashAlgorithm algorithm, string expected) + { + var result = input.Hash(algorithm); Assert.That(result, Is.EqualTo(expected)); } public static IEnumerable GetAlgorithms() { - yield return new object[] { MD5.Create(), "3e25960a79dbc69b674cd4ec67a72c62" }; + yield return new object[] { "Hello world", MD5.Create(), "3e25960a79dbc69b674cd4ec67a72c62" }; - yield return new object[] { SHA1.Create(), "7b502c3a1f48c8609ae212cdfb639dee39673f5e" }; + yield return new object[] { "Hello world", SHA1.Create(), "7b502c3a1f48c8609ae212cdfb639dee39673f5e" }; } [Test] - public void MD5_returns_correct_hash() + public void MD5_returns_correct_hash_with_specified_encoding() + { + var result = "Hello world".MD5(Encoding.UTF8); + + const string expected = "3e25960a79dbc69b674cd4ec67a72c62"; + + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void MD5_returns_correct_hash_with_default_encoding() { var result = "Hello world".MD5(); @@ -34,5 +54,21 @@ public void MD5_returns_correct_hash() Assert.That(result, Is.EqualTo(expected)); } + + [Test] + [TestCaseSource(nameof(GetEncodings))] + public void MD5_returns_correct_hash_with_specified_encoding(string input, Encoding encoding, string expected) + { + var result = input.MD5(encoding); + + Assert.That(result, Is.EqualTo(expected)); + } + + public static IEnumerable GetEncodings() + { + yield return new object[] { "string with swedish characters: ö ä å", Encoding.UTF8, "29f815f91399c52782a11e5206ae2b9f" }; + + yield return new object[] { "string with swedish characters: ö ä å", Encoding.ASCII, "b65d919f7a01ca0ca25b694c50a77c35" }; + } } }