using VoiceCat.Crypto; namespace VoiceCat.Tests; public class TofuTlsTests { [Fact] public void PinCreatesMissingParentDirectory() { string root = Path.Combine(Path.GetTempPath(), "voicecat-tofu-parent-" + Guid.NewGuid()); string path = Path.Combine(root, "nested", "pins.txt"); try { var store = new TofuStore(path); store.Pin("localhost", 8384, new string('a', 64)); Assert.True(File.Exists(path)); Assert.Equal(TofuStatus.Matched, new TofuStore(path).Check("localhost", 8384, new string('A', 64))); } finally { if (Directory.Exists(root)) Directory.Delete(root, true); } } [Fact] public void RealHandshakesRequireAcceptanceAndRejectChangedCertificatesAfterRestart() { string directory = Path.Combine(Path.GetTempPath(), "voicecat-tofu-tls-" + Guid.NewGuid()); Directory.CreateDirectory(directory); string path = Path.Combine(directory, "pins.txt"); try { using var credentials = ServerCredentials.LoadOrCreate(Path.Combine(directory, "server"), "server"); var store = new TofuStore(path); using (var server = credentials.CreateTlsSession()) using (var rejected = TlsSession.CreateClient(fingerprint => { Assert.Equal(TofuStatus.FirstConnect, store.Check("localhost", 9987, fingerprint)); return false; })) Assert.ThrowsAny(() => TlsTests.Handshake(rejected, server)); Assert.False(File.Exists(path)); using (var server = credentials.CreateTlsSession()) using (var accepted = TlsSession.CreateClient(fingerprint => { Assert.Equal(TofuStatus.FirstConnect, store.Check("localhost", 9987, fingerprint)); store.Pin("localhost", 9987, fingerprint); return true; })) TlsTests.Handshake(accepted, server); store = new(path); using (var server = credentials.CreateTlsSession()) using (var returning = TlsSession.CreateClient(fingerprint => store.Check("localhost", 9987, fingerprint) == TofuStatus.Matched)) TlsTests.Handshake(returning, server); using var rotated = ServerCredentials.LoadOrCreate(Path.Combine(directory, "rotated"), "server"); using (var server = rotated.CreateTlsSession()) using (var mismatch = TlsSession.CreateClient(fingerprint => { Assert.Equal(TofuStatus.Mismatch, store.Check("localhost", 9987, fingerprint)); return false; })) Assert.ThrowsAny(() => TlsTests.Handshake(mismatch, server)); Assert.Equal(TofuStatus.Matched, new TofuStore(path).Check("localhost", 9987, credentials.CertificateFingerprint)); } finally { Directory.Delete(directory, true); } } }