Files
hrynco-common/HrynCo.Common.Tests/SecretProtectorTests.cs
T
Anatolii Grynchuk 85b362e8cd chore: add hrynco common library solution
- add the standalone HrynCo.Common solution and projects
- include the shared common library source and tests
- add package metadata and a repo gitignore
2026-05-01 00:17:34 +03:00

82 lines
2.7 KiB
C#

namespace HrynCo.Common.Tests;
using System.Security.Cryptography;
using HrynCo.Common.Security;
using FluentAssertions;
using Xunit;
public sealed class SecretProtectorTests
{
[Fact]
public void Constructor_ShouldRejectMissingKey()
{
Action act = () => _ = new SecretProtector(string.Empty);
act.Should().Throw<InvalidOperationException>()
.WithMessage("Secret encryption key is not configured.");
}
[Fact]
public void Constructor_ShouldRejectInvalidKeyLength()
{
string key = Convert.ToBase64String(RandomNumberGenerator.GetBytes(31));
Action act = () => _ = new SecretProtector(key);
act.Should().Throw<InvalidOperationException>()
.WithMessage("Secret encryption key must be 32 bytes encoded as Base64.");
}
[Fact]
public void ProtectAndUnprotect_ShouldRoundTripPlaintext()
{
string key = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32));
var protector = new SecretProtector(key);
string protectedValue = protector.Protect("hello world");
string plaintext = protector.Unprotect(protectedValue);
protectedValue.Should().StartWith("v1:");
plaintext.Should().Be("hello world");
}
[Fact]
public void Unprotect_ShouldRejectUnsupportedFormat()
{
string key = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32));
var protector = new SecretProtector(key);
Action act = () => protector.Unprotect("v2:payload");
act.Should().Throw<InvalidOperationException>()
.WithMessage("Unsupported protected value format.");
}
[Fact]
public void Unprotect_ShouldFailWhenProtectedValueIsTamperedWith()
{
string key = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32));
var protector = new SecretProtector(key);
string protectedValue = protector.Protect("hello world");
string tamperedValue = protectedValue[..^1] + (protectedValue.EndsWith('A') ? 'B' : 'A');
Action act = () => protector.Unprotect(tamperedValue);
act.Should().Throw<CryptographicException>();
}
[Fact]
public void Unprotect_ShouldFailWhenUsingTheWrongKey()
{
string originalKey = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32));
string otherKey = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32));
var protector = new SecretProtector(originalKey);
var wrongProtector = new SecretProtector(otherKey);
string protectedValue = protector.Protect("hello world");
Action act = () => wrongProtector.Unprotect(protectedValue);
act.Should().Throw<CryptographicException>();
}
}