69 lines
3.7 KiB
C#
69 lines
3.7 KiB
C#
using System.Security.Cryptography;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Formats.Asn1;
|
|
using VoiceCat.Crypto;
|
|
|
|
namespace VoiceCat.Tests;
|
|
|
|
public class IdentityTests
|
|
{
|
|
[Fact]
|
|
public void CredentialsSurviveRestartAndBindIdentityIntoCertificate()
|
|
{
|
|
string directory = Path.Combine(Path.GetTempPath(), "voicecat-credentials-" + Guid.NewGuid());
|
|
try
|
|
{
|
|
string identityFingerprint, certificateFingerprint;
|
|
using (var credentials = ServerCredentials.LoadOrCreate(directory, "Server, with punctuation"))
|
|
{
|
|
identityFingerprint = credentials.Identity.Fingerprint;
|
|
certificateFingerprint = credentials.CertificateFingerprint;
|
|
using var tls = credentials.CreateTlsSession();
|
|
Assert.False(tls.IsReady);
|
|
byte[] identity = File.ReadAllBytes(Path.Combine(directory, "identity.key"));
|
|
Assert.Equal(96, identity.Length);
|
|
Assert.Equal(identity[..32], identity[64..]);
|
|
using var certificate = X509Certificate2.CreateFromPem(File.ReadAllText(Path.Combine(directory, "server.crt")));
|
|
var san = new AsnReader(certificate.Extensions["2.5.29.17"]!.RawData, AsnEncodingRules.DER).ReadSequence();
|
|
Assert.Equal("urn:voicecat:identity:ed25519:" + Convert.ToHexString(credentials.Identity.PublicKey).ToLowerInvariant(),
|
|
san.ReadCharacterString(UniversalTagNumber.IA5String, new Asn1Tag(TagClass.ContextSpecific, 6)));
|
|
Assert.False(san.HasData);
|
|
}
|
|
using var restored = ServerCredentials.LoadOrCreate(directory, "ignored after creation");
|
|
Assert.Equal(identityFingerprint, restored.Identity.Fingerprint);
|
|
Assert.Equal(certificateFingerprint, restored.CertificateFingerprint);
|
|
File.Delete(Path.Combine(directory, "server.key"));
|
|
Assert.Throws<InvalidDataException>(() => ServerCredentials.LoadOrCreate(directory, "unchanged"));
|
|
using var stillPresent = ServerIdentity.Load(Path.Combine(directory, "identity.key"));
|
|
Assert.Equal(identityFingerprint, stillPresent.Fingerprint);
|
|
}
|
|
finally { if (Directory.Exists(directory)) Directory.Delete(directory, true); }
|
|
}
|
|
|
|
[Fact]
|
|
public void TofuRequiresExplicitPinAndPreservesCppFileFormat()
|
|
{
|
|
string directory = Path.Combine(Path.GetTempPath(), "voicecat-pins-" + Guid.NewGuid());
|
|
Directory.CreateDirectory(directory);
|
|
string path = Path.Combine(directory, "pins.txt");
|
|
string fingerprint = Convert.ToHexString(RandomNumberGenerator.GetBytes(32));
|
|
try
|
|
{
|
|
var store = new TofuStore(path);
|
|
Assert.Equal(TofuStatus.FirstConnect, store.Check("localhost", 9987, fingerprint));
|
|
Assert.False(File.Exists(path));
|
|
store.Pin("localhost", 9987, fingerprint);
|
|
Assert.Equal($"localhost:9987 {fingerprint.ToLowerInvariant()}\n", File.ReadAllText(path));
|
|
store = new(path);
|
|
Assert.Equal(TofuStatus.Matched, store.Check("localhost", 9987, fingerprint));
|
|
Assert.Equal(TofuStatus.Mismatch, store.Check("localhost", 9987, new string('0', 64)));
|
|
Assert.Equal(TofuStatus.Matched, new TofuStore(path).Check("localhost", 9987, fingerprint));
|
|
store.Remove("localhost", 9987);
|
|
Assert.Equal(TofuStatus.FirstConnect, new TofuStore(path).Check("localhost", 9987, fingerprint));
|
|
File.WriteAllText(path, "localhost:9987 " + new string('g', 64));
|
|
Assert.Throws<InvalidDataException>(() => new TofuStore(path));
|
|
}
|
|
finally { Directory.Delete(directory, true); }
|
|
}
|
|
}
|