Skip to content

Commit 3d974e3

Browse files
Added base64 checksum output
1 parent 2d67e7f commit 3d974e3

3 files changed

Lines changed: 35 additions & 15 deletions

File tree

OutSystems.NetChecksumUtils.UnitTests/NetChecksumUtils.ComputeChecksum.Tests.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ private static string GetExpectedHash(string algorithm, string text)
3434
};
3535
}
3636

37+
private static string GetExpectedBase64(string algorithm, string text)
38+
{
39+
byte[] data = Encoding.UTF8.GetBytes(text);
40+
return algorithm.Trim().ToUpperInvariant() switch
41+
{
42+
"SHA256" or "SHA-256" => Convert.ToBase64String(SHA256.HashData(data)),
43+
"SHA512" or "SHA-512" => Convert.ToBase64String(SHA512.HashData(data)),
44+
"SHA3_256" or "SHA3-256" => Convert.ToBase64String(SHA3_256.HashData(data)),
45+
"MD5" => Convert.ToBase64String(MD5.HashData(data)),
46+
_ => throw new ArgumentException("Unsupported algorithm in test helper", nameof(algorithm))
47+
};
48+
}
49+
3750
#endregion
3851

3952
#region ComputeChecksum Tests
@@ -53,12 +66,13 @@ public void ComputeChecksum_ValidInput_ReturnsCorrectHash(string algorithm, stri
5366
string expected = GetExpectedHash(algorithm, text);
5467

5568
// Act
56-
_sut.ComputeChecksum(algorithm, text, out string actual, out long ticks);
69+
_sut.ComputeChecksum(algorithm, text, out string actualHex, out string actualBase64, out long ticks);
5770

5871
// Assert
5972
Assert.Multiple(() =>
6073
{
61-
Assert.That(actual, Is.EqualTo(expected), $"Hash mismatch for {algorithm}");
74+
Assert.That(actualHex, Is.EqualTo(expected), $"Hex hash mismatch for {algorithm}");
75+
Assert.That(actualBase64, Is.EqualTo(GetExpectedBase64(algorithm, text)), $"Base64 hash mismatch for {algorithm}");
6276
Assert.That(ticks, Is.GreaterThanOrEqualTo(0), "Duration should be non-negative.");
6377
});
6478
}
@@ -120,8 +134,8 @@ public void Methods_NullInputs_ThrowArgumentNullException()
120134
Assert.Multiple(() =>
121135
{
122136
// ComputeChecksum null checks
123-
Assert.Throws<ArgumentNullException>(() => _sut.ComputeChecksum(null!, "text", out _, out _));
124-
Assert.Throws<ArgumentNullException>(() => _sut.ComputeChecksum("SHA256", null!, out _, out _));
137+
Assert.Throws<ArgumentNullException>(() => _sut.ComputeChecksum(null!, "text", out _, out _, out _));
138+
Assert.Throws<ArgumentNullException>(() => _sut.ComputeChecksum("SHA256", null!, out _, out _, out _));
125139

126140
// VerifyChecksum null checks
127141
Assert.Throws<ArgumentNullException>(() => _sut.VerifyChecksum(null!, "text", "hash", out _, out _));
@@ -139,7 +153,7 @@ public void Methods_NullInputs_ThrowArgumentNullException()
139153
public void Methods_InvalidAlgorithm_ThrowsArgumentException(string invalidAlgo)
140154
{
141155
Assert.Throws<ArgumentException>(() =>
142-
_sut.ComputeChecksum(invalidAlgo, "text", out _, out _));
156+
_sut.ComputeChecksum(invalidAlgo, "text", out _, out _, out _));
143157
}
144158

145159
#endregion

OutSystems.NetChecksumUtils/INetChecksumUtils.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ void ComputeChecksum(
2222
string textToHash,
2323
[OSParameterAttribute(Description = "Output parameter that receives the computed checksum as an uppercase hexadecimal string.")]
2424
out string checksumText,
25+
[OSParameterAttribute(Description = "Output parameter that receives the computed checksum as a Base64 string.")]
26+
out string checksumBase64,
2527
[OSParameterAttribute(Description = "Output parameter that receives the duration of the hashing operation in ticks.")]
2628
out long operationDuration
2729
);
@@ -35,7 +37,7 @@ void VerifyChecksum(
3537
string algorithm,
3638
[OSParameterAttribute(Description = "The name of the hashing algorithm to use. Supported values (case-insensitive): \"SHA256\", \"SHA-256\", \"SHA512\", \"SHA-512\", \"MD5\", \"SHA3-256\", \"SHA3_256\".")]
3739
string text,
38-
[OSParameterAttribute(Description = "The text to compute the checksum for. The text is encoded as UTF-8 before hashing.")]
40+
[OSParameterAttribute(Description = "The text to compute the checksum for uppercase hex or base64). The text is encoded as UTF-8 before hashing.")]
3941
string existingChecksum,
4042
[OSParameterAttribute(Description = "Output parameter that receives the computed checksum as an uppercase hexadecimal string.")]
4143
out bool isValid,

OutSystems.NetChecksumUtils/NetChecksumUtils.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ namespace OutSystems.NetChecksumUtils
1212
/// </summary>
1313
public class NetChecksumUtils : INetChecksumUtils
1414
{
15-
static (string Hex, TimeSpan Elapsed) ComputeChecksum(Func<byte[], byte[]> hashFunc, byte[] bytes)
15+
static (byte[] HashBytes, TimeSpan Elapsed) ComputeChecksum(Func<byte[], byte[]> hashFunc, byte[] bytes)
1616
{
1717
var sw = Stopwatch.StartNew();
1818
byte[] hashBytes = hashFunc(bytes);
1919
sw.Stop();
20-
return (Convert.ToHexString(hashBytes), sw.Elapsed);
20+
return (hashBytes, sw.Elapsed);
2121
}
2222

2323
/// <summary>
@@ -59,7 +59,7 @@ private static Func<byte[], byte[]> GetHashFunction(string algorithm)
5959
/// <exception cref="ArgumentException">Thrown when <paramref name="algorithm"/> is not recognized/supported.</exception>
6060
public void ComputeChecksum(
6161
string algorithm, string textToHash,
62-
out string checksumText, out long operationDurationInTicks)
62+
out string checksumTextHex, out string checksumTextBase64, out long operationDurationInTicks)
6363
{
6464
// Ensure inputs are not null before proceeding
6565
ArgumentNullException.ThrowIfNull(algorithm);
@@ -72,10 +72,11 @@ public void ComputeChecksum(
7272
var hashFunc = GetHashFunction(algorithm);
7373

7474
// 3. Execute the hashing logic and measure performance.
75-
var (computedChecksum, elapsed) = ComputeChecksum(hashFunc, inputBytes);
75+
var (hashBytes, elapsed) = ComputeChecksum(hashFunc, inputBytes);
7676

77-
// 4. Assign results to output parameters
78-
checksumText = computedChecksum;
77+
// 4. Assign results to output parameters (hex + base64)
78+
checksumTextHex = Convert.ToHexString(hashBytes);
79+
checksumTextBase64 = Convert.ToBase64String(hashBytes);
7980
operationDurationInTicks = elapsed.Ticks;
8081
}
8182

@@ -87,7 +88,7 @@ public void ComputeChecksum(
8788
/// "SHA256", "SHA-256", "SHA512", "SHA-512", "MD5".
8889
/// </param>
8990
/// <param name="text">The input text to hash (UTF-8 encoded before hashing).</param>
90-
/// <param name="existingChecksum">The checksum to compare against (hex string).</param>
91+
/// <param name="existingChecksum">The checksum to compare against (base64 or hex string).</param>
9192
/// <param name="isValid">Output parameter set to true when the computed checksum equals <paramref name="existingChecksum"/> (case-insensitive).</param>
9293
/// <param name="operationDuration">Output parameter that receives the duration, in ticks, of the entire verification operation (includes hashing + comparison).</param>
9394
/// <exception cref="ArgumentNullException">Thrown when <paramref name="algorithm"/>, <paramref name="text"/> or <paramref name="existingChecksum"/> is null.</exception>
@@ -109,8 +110,11 @@ public void VerifyChecksum(
109110

110111
// 3. Measure the whole operation: hashing + comparison
111112
var sw = Stopwatch.StartNew();
112-
var (newChecksum, _) = ComputeChecksum(hashFunc, inputBytes);
113-
isValid = string.Equals(newChecksum, existingChecksum, StringComparison.OrdinalIgnoreCase);
113+
var (hashBytes, _) = ComputeChecksum(hashFunc, inputBytes);
114+
var newHex = Convert.ToHexString(hashBytes);
115+
var newBase64 = Convert.ToBase64String(hashBytes);
116+
isValid = string.Equals(newHex, existingChecksum, StringComparison.OrdinalIgnoreCase)
117+
|| string.Equals(newBase64, existingChecksum, StringComparison.Ordinal);
114118
sw.Stop();
115119

116120
// 4. Return operation duration in ticks (includes comparison step)

0 commit comments

Comments
 (0)