mirror of https://github.com/ErsatzTV/ErsatzTV.git
17 changed files with 334 additions and 45 deletions
@ -1,3 +1,3 @@
@@ -1,3 +1,3 @@
|
||||
namespace ErsatzTV.Application.Plex; |
||||
|
||||
public record PlexConnectionParametersViewModel(Uri Uri, string AuthToken); |
||||
public record PlexConnectionParametersViewModel(string Address, string AuthToken); |
||||
|
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
using ErsatzTV.Core.Security; |
||||
using NUnit.Framework; |
||||
using Shouldly; |
||||
|
||||
namespace ErsatzTV.Core.Tests.Security; |
||||
|
||||
[TestFixture] |
||||
public class InternalUrlSignerTests |
||||
{ |
||||
[Test] |
||||
public void Verify_Alpha_Exp_Should_Not_Throw() |
||||
{ |
||||
bool actual = InternalUrlSigner.Verify("abc", "sig"); |
||||
actual.ShouldBeFalse(); |
||||
} |
||||
|
||||
[Test] |
||||
public void Verify_Long_Exp_Should_Not_Throw() |
||||
{ |
||||
bool actual = InternalUrlSigner.Verify("99999999999999", "sig"); |
||||
actual.ShouldBeFalse(); |
||||
} |
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
using System.Globalization; |
||||
using System.Security.Cryptography; |
||||
using System.Text; |
||||
|
||||
namespace ErsatzTV.Core.Security; |
||||
|
||||
public static class InternalUrlSigner |
||||
{ |
||||
private static readonly byte[] Key = RandomNumberGenerator.GetBytes(32); |
||||
|
||||
public static string Sign(DateTimeOffset expires, params string[] parts) |
||||
{ |
||||
string canonical = string.Join('\0', parts) + '\0' + expires.ToUnixTimeSeconds(); |
||||
byte[] bytes = Encoding.UTF8.GetBytes(canonical); |
||||
using HMACSHA256 hmac = new HMACSHA256(Key); |
||||
byte[] hash = hmac.ComputeHash(bytes); |
||||
return Convert.ToHexString(hash).ToLowerInvariant(); |
||||
} |
||||
|
||||
public static bool Verify(string exp, string sig, params string[] parts) |
||||
{ |
||||
if (!long.TryParse(exp, CultureInfo.InvariantCulture, out long num)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
try |
||||
{ |
||||
DateTimeOffset expires = DateTimeOffset.FromUnixTimeSeconds(num); |
||||
string expected = Sign(expires, parts); |
||||
byte[] expectedBytes = Encoding.UTF8.GetBytes(expected); |
||||
byte[] actualBytes = Encoding.UTF8.GetBytes(sig); |
||||
return DateTimeOffset.Now < expires && CryptographicOperations.FixedTimeEquals(expectedBytes, actualBytes); |
||||
} |
||||
catch (ArgumentOutOfRangeException) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue