|
| 1 | +namespace HashGate.HttpClient.Tests; |
| 2 | + |
| 3 | +public class HmacAuthenticationSharedTests |
| 4 | +{ |
| 5 | + [Fact] |
| 6 | + public void CreateStringToSign_CreatesExpectedFormat() |
| 7 | + { |
| 8 | + var method = "get"; |
| 9 | + var pathAndQuery = "/api/resource?x=1"; |
| 10 | + var headers = new[] { "value1", "value2" }; |
| 11 | + var result = HmacAuthenticationShared.CreateStringToSign(method, pathAndQuery, headers); |
| 12 | + |
| 13 | + Assert.Equal("GET\n/api/resource?x=1\nvalue1;value2", result); |
| 14 | + } |
| 15 | + |
| 16 | + [Fact] |
| 17 | + public void CreateStringToSign_EmptyHeaders_CreatesExpectedFormat() |
| 18 | + { |
| 19 | + var method = "post"; |
| 20 | + var pathAndQuery = "/api/empty"; |
| 21 | + var headers = Array.Empty<string>(); |
| 22 | + var result = HmacAuthenticationShared.CreateStringToSign(method, pathAndQuery, headers); |
| 23 | + |
| 24 | + Assert.Equal("POST\n/api/empty\n", result); |
| 25 | + } |
| 26 | + |
| 27 | + [Fact] |
| 28 | + public void CreateStringToSign_SingleHeader_CreatesExpectedFormat() |
| 29 | + { |
| 30 | + var method = "put"; |
| 31 | + var pathAndQuery = "/api/one"; |
| 32 | + var headers = new[] { "onlyone" }; |
| 33 | + var result = HmacAuthenticationShared.CreateStringToSign(method, pathAndQuery, headers); |
| 34 | + |
| 35 | + Assert.Equal("PUT\n/api/one\nonlyone", result); |
| 36 | + } |
| 37 | + |
| 38 | + [Theory] |
| 39 | + [InlineData("", "", true)] |
| 40 | + [InlineData(" ", " ", true)] |
| 41 | + [InlineData("abc", "", false)] |
| 42 | + [InlineData("", "abc", false)] |
| 43 | + public void FixedTimeEquals_EmptyAndWhitespaceCases(string left, string right, bool expected) |
| 44 | + { |
| 45 | + Assert.Equal(expected, HmacAuthenticationShared.FixedTimeEquals(left, right)); |
| 46 | + } |
| 47 | + |
| 48 | + [Theory] |
| 49 | + [InlineData("abc", "abc", true)] |
| 50 | + [InlineData("abc", "def", false)] |
| 51 | + [InlineData("abc", "abcd", false)] |
| 52 | + [InlineData("abc", "abc ", false)] |
| 53 | + public void FixedTimeEquals_ComparesCorrectly(string left, string right, bool expected) |
| 54 | + { |
| 55 | + Assert.Equal(expected, HmacAuthenticationShared.FixedTimeEquals(left, right)); |
| 56 | + } |
| 57 | + |
| 58 | + |
| 59 | + [Fact] |
| 60 | + public void GenerateAuthorizationHeader_CreatesExpectedHeader() |
| 61 | + { |
| 62 | + var client = "abc123"; |
| 63 | + var signedHeaders = new[] { "host", "date" }; |
| 64 | + var signature = "xyz789"; |
| 65 | + var header = HmacAuthenticationShared.GenerateAuthorizationHeader(client, signedHeaders, signature); |
| 66 | + |
| 67 | + Assert.Equal("HMAC Client=abc123&SignedHeaders=host;date&Signature=xyz789", header); |
| 68 | + } |
| 69 | + |
| 70 | + [Fact] |
| 71 | + public void GenerateAuthorizationHeader_EmptyHeaders_CreatesExpectedHeader() |
| 72 | + { |
| 73 | + var client = "empty"; |
| 74 | + var signedHeaders = Array.Empty<string>(); |
| 75 | + var signature = "sig"; |
| 76 | + var header = HmacAuthenticationShared.GenerateAuthorizationHeader(client, signedHeaders, signature); |
| 77 | + |
| 78 | + Assert.Equal("HMAC Client=empty&SignedHeaders=&Signature=sig", header); |
| 79 | + } |
| 80 | + |
| 81 | + [Fact] |
| 82 | + public void GenerateSignature_EmptyInputs_ReturnsExpectedBase64() |
| 83 | + { |
| 84 | + var signature = HmacAuthenticationShared.GenerateSignature("", ""); |
| 85 | + Assert.Equal(44, signature.Length); |
| 86 | + Assert.True(Convert.TryFromBase64String(signature, new Span<byte>(new byte[32]), out _)); |
| 87 | + } |
| 88 | + |
| 89 | + [Fact] |
| 90 | + public void GenerateSignature_ReturnsExpectedBase64() |
| 91 | + { |
| 92 | + var stringToSign = "GET\n/api/resource?x=1\nvalue1;value2"; |
| 93 | + var secretKey = "mysecret"; |
| 94 | + var signature = HmacAuthenticationShared.GenerateSignature(stringToSign, secretKey); |
| 95 | + |
| 96 | + // Validate base64 length for SHA256 |
| 97 | + Assert.Equal(44, signature.Length); |
| 98 | + |
| 99 | + // Should be valid base64 |
| 100 | + Assert.True(Convert.TryFromBase64String(signature, new Span<byte>(new byte[32]), out _)); |
| 101 | + } |
| 102 | +} |
0 commit comments