85bf329d93
Implements LineSignature.IsValid() using HMAC-SHA256 + FixedTimeEquals to prevent timing attacks; includes xUnit tests for valid, tampered, and null/empty header cases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
48 lines
1.3 KiB
C#
48 lines
1.3 KiB
C#
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using ROLAC.API.Services.Notifications;
|
|
using Xunit;
|
|
|
|
namespace ROLAC.API.Tests.Services.Notifications;
|
|
|
|
public class LineSignatureTests
|
|
{
|
|
private const string Secret = "test-channel-secret";
|
|
|
|
private static string Sign(string body)
|
|
{
|
|
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(Secret));
|
|
return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(body)));
|
|
}
|
|
|
|
[Fact]
|
|
public void IsValid_ReturnsTrue_ForMatchingSignature()
|
|
{
|
|
var body = """{"events":[]}""";
|
|
var signature = Sign(body);
|
|
|
|
var result = LineSignature.IsValid(Secret, Encoding.UTF8.GetBytes(body), signature);
|
|
|
|
Assert.True(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void IsValid_ReturnsFalse_ForTamperedBody()
|
|
{
|
|
var signature = Sign("""{"events":[]}""");
|
|
|
|
var result = LineSignature.IsValid(Secret, Encoding.UTF8.GetBytes("""{"events":[1]}"""), signature);
|
|
|
|
Assert.False(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void IsValid_ReturnsFalse_ForNullOrEmptyHeader()
|
|
{
|
|
var body = Encoding.UTF8.GetBytes("""{"events":[]}""");
|
|
|
|
Assert.False(LineSignature.IsValid(Secret, body, null));
|
|
Assert.False(LineSignature.IsValid(Secret, body, ""));
|
|
}
|
|
}
|