nc_program_manager/NcProgramManager.Tests/Unit/LicenseValidatorTests.cs
dtrentin 39a9566858 feat(07-license-core): RSA offline license core
Phase 07 complete:
- IMachineFingerprint + ILicenseValidator interfaces
- MachineFingerprint: WMI CPU ProcessorID + BaseBoard SerialNumber
- LicenseValidator: RSACryptoServiceProvider + SHA256, injectable public key
- LicenseFile.TryRead: out-param bool, no exceptions from file I/O
- 6 NUnit tests (valid/wrong-machine/tampered/empty/not-base64/missing-file)
- 118 tests total, 116 pass, 2 Fanuc FOCAS ignored (Windows DLL)
- Fix: missing 'using System' in CncMachineFactoryTests.cs
- Fix: Dockerfile.test updated for NcProgramManager rename

PublicKeyXml = PLACEHOLDER until Phase 09 generates real key pair.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 22:58:14 +02:00

80 lines
2.3 KiB
C#

using System;
using System.Security.Cryptography;
using System.Text;
using NUnit.Framework;
using NcProgramManager.Licensing;
namespace NcProgramManager.Tests.Unit
{
[TestFixture]
internal class LicenseValidatorTests
{
private RSACryptoServiceProvider _rsa;
private string _publicKeyXml;
private LicenseValidator _validator;
[SetUp]
public void SetUp()
{
_rsa = new RSACryptoServiceProvider(2048);
_publicKeyXml = _rsa.ToXmlString(false);
_validator = new LicenseValidator(_publicKeyXml);
}
[TearDown]
public void TearDown()
{
_rsa.Dispose();
}
private string Sign(string fingerprint)
{
byte[] data = Encoding.UTF8.GetBytes(fingerprint);
byte[] sig = _rsa.SignData(data, new SHA256CryptoServiceProvider());
return Convert.ToBase64String(sig);
}
[Test]
public void Validate_ValidLicense_ReturnsTrue()
{
string fingerprint = "CPU123BOARD456";
string license = Sign(fingerprint);
Assert.IsTrue(_validator.Validate(fingerprint, license));
}
[Test]
public void Validate_WrongMachineFingerprint_ReturnsFalse()
{
string license = Sign("CPU123BOARD456");
Assert.IsFalse(_validator.Validate("DIFFERENT_MACHINE", license));
}
[Test]
public void Validate_TamperedLicense_ReturnsFalse()
{
string license = Sign("CPU123BOARD456");
string tampered = license.Substring(0, license.Length - 4) + "AAAA";
Assert.IsFalse(_validator.Validate("CPU123BOARD456", tampered));
}
[Test]
public void Validate_EmptyLicense_ReturnsFalse()
{
Assert.IsFalse(_validator.Validate("CPU123BOARD456", string.Empty));
}
[Test]
public void Validate_NotBase64_ReturnsFalse()
{
Assert.IsFalse(_validator.Validate("CPU123BOARD456", "not-base64!!!"));
}
[Test]
public void LicenseFile_TryRead_NonExistentPath_ReturnsFalse()
{
bool result = LicenseFile.TryRead(@"C:\nonexistent\path\license.lic", out string base64);
Assert.IsFalse(result);
Assert.IsNull(base64);
}
}
}