Skip to content

Commit cc1003b

Browse files
authored
Add hmac_sha1 and hmac_sha256 filters (#753)
1 parent 88673c8 commit cc1003b

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

Fluid.Tests/MiscFiltersTests.cs

+44
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,50 @@ public async Task Sha256()
913913
Assert.Equal("c7ac4687585ab5d3d5030db5a5cfc959fdf4e608cc396f1f615db345e35adb9e", result.ToStringValue());
914914
}
915915

916+
[Theory]
917+
[InlineData(null, "Fluid", "")]
918+
[InlineData("secret_key", null, "")]
919+
[InlineData("", "", "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d")]
920+
[InlineData("", "Fluid", "47ab4d87fabf7a7162d59c57298780904de9e245")]
921+
[InlineData("secret_key", "Fluid", "1061ea276551355150b8581aa64dca829d41e357")]
922+
public async Task HmacSha1(string key, string value, string expected)
923+
{
924+
// Arrange
925+
FluidValue input = value is null
926+
? NilValue.Empty
927+
: new StringValue(value);
928+
var arguments = new FilterArguments(FluidValue.Create(key, TemplateOptions.Default));
929+
var context = new TemplateContext();
930+
931+
// Act
932+
var result = await MiscFilters.HmacSha1(input, arguments, context);
933+
934+
// Assert
935+
Assert.Equal(expected, result.ToStringValue());
936+
}
937+
938+
[Theory]
939+
[InlineData(null, "Fluid", "")]
940+
[InlineData("secret_key", null, "")]
941+
[InlineData("", "", "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad")]
942+
[InlineData("", "Fluid", "e9f2db8bd3900c469e4b560227c5d53b48f644208a13de05bb400f7611d1a623")]
943+
[InlineData("secret_key", "Fluid", "ac08ee5cdd007e1069680e93eb512049f5ff12afd0fe101de5c9b5043a047ea4")]
944+
public async Task HmacSha256(string key, string value, string expected)
945+
{
946+
// Arrange
947+
FluidValue input = value is null
948+
? NilValue.Empty
949+
: new StringValue(value);
950+
var arguments = new FilterArguments(FluidValue.Create(key, TemplateOptions.Default));
951+
var context = new TemplateContext();
952+
953+
// Act
954+
var result = await MiscFilters.HmacSha256(input, arguments, context);
955+
956+
// Assert
957+
Assert.Equal(expected, result.ToStringValue());
958+
}
959+
916960
public static class TestObjects
917961
{
918962
public class Node

Fluid/Filters/MiscFilters.cs

+45
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
using Fluid.Utils;
12
using Fluid.Values;
23
using System.Buffers;
34
using System.Globalization;
45
using System.Net;
56
using System.Reflection;
7+
using System.Security.Cryptography;
68
using System.Text;
79
using System.Text.Json;
810
using TimeZoneConverter;
@@ -41,6 +43,8 @@ public static FilterCollection WithMiscFilters(this FilterCollection filters)
4143
filters.AddFilter("md5", MD5);
4244
filters.AddFilter("sha1", Sha1);
4345
filters.AddFilter("sha256", Sha256);
46+
filters.AddFilter("hmac_sha1", HmacSha1);
47+
filters.AddFilter("hmac_sha256", HmacSha256);
4448

4549
return filters;
4650
}
@@ -931,5 +935,46 @@ public static ValueTask<FluidValue> Sha256(FluidValue input, FilterArguments arg
931935
return new StringValue(builder.ToString());
932936
#endif
933937
}
938+
939+
public static ValueTask<FluidValue> HmacSha1(FluidValue input, FilterArguments arguments, TemplateContext context) => ComputeHmac("HMACSHA1", input, arguments);
940+
941+
public static ValueTask<FluidValue> HmacSha256(FluidValue input, FilterArguments arguments, TemplateContext context) => ComputeHmac("HMACSHA256", input, arguments);
942+
943+
private static ValueTask<FluidValue> ComputeHmac(string algorithm, FluidValue input, FilterArguments arguments)
944+
{
945+
var key = arguments.At(0);
946+
if (key.IsNil() || input.IsNil())
947+
{
948+
return StringValue.Empty;
949+
}
950+
951+
var value = input.ToStringValue();
952+
var keyBytes = Encoding.UTF8.GetBytes(key.ToStringValue());
953+
954+
#if NET6_0_OR_GREATER
955+
#pragma warning disable CA5350
956+
var hash = algorithm switch
957+
{
958+
"HMACSHA1" => HMACSHA1.HashData(keyBytes, Encoding.UTF8.GetBytes(value)),
959+
"HMACSHA256" => HMACSHA256.HashData(keyBytes, Encoding.UTF8.GetBytes(value)),
960+
_ => throw new ArgumentException("Unsupported HMAC algorithm", nameof(algorithm))
961+
};
962+
#pragma warning restore CA5350
963+
964+
return new StringValue(HexUtilities.ToHexLower(hash));
965+
#else
966+
using var provider = HMAC.Create(algorithm);
967+
provider.Key = keyBytes;
968+
var builder = new StringBuilder(64);
969+
#pragma warning disable CA1850
970+
foreach (var b in provider.ComputeHash(Encoding.UTF8.GetBytes(value)))
971+
#pragma warning restore CA1850
972+
{
973+
builder.Append(b.ToString("x2"));
974+
}
975+
976+
return new StringValue(builder.ToString());
977+
#endif
978+
}
934979
}
935980
}

0 commit comments

Comments
 (0)