75 lines
3.3 KiB
C#
75 lines
3.3 KiB
C#
using System.Text.Json;
|
|
using FinalFactory.Rendezvous.Client;
|
|
using FinalFactory.Rendezvous.Contracts;
|
|
|
|
namespace FinalFactory.Rendezvous.Tests.Contracts;
|
|
|
|
public sealed class TraversalTokenCodecTests
|
|
{
|
|
[Fact]
|
|
public void IntroductionTokenBindsAttemptAndRedactsTheFixedTicket()
|
|
{
|
|
JoinAttemptId attemptId = new(Guid.Parse("00000000-0000-0000-0000-000000000301"));
|
|
string authenticator = Credential('T');
|
|
|
|
string encoded = NatIntroductionTokenCodec.Encode(attemptId, authenticator);
|
|
|
|
Assert.Equal(NatIntroductionTokenCodec.EncodedLength, encoded.Length);
|
|
Assert.True(encoded.Length <= ContractLimits.LiteNetLibNatTokenMaxCharacters);
|
|
Assert.True(NatIntroductionTokenCodec.TryDecode(encoded, out NatIntroductionToken? decoded));
|
|
Assert.NotNull(decoded);
|
|
Assert.Equal(attemptId, decoded.AttemptId);
|
|
Assert.Equal(encoded, decoded.ConnectionTicket);
|
|
Assert.DoesNotContain(encoded, decoded.ToString(), StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void ConnectionTicketMatchesTheVersionedV1Vector()
|
|
{
|
|
using JsonDocument vector = JsonDocument.Parse(ContractTestFiles.Read("connection-ticket.json"));
|
|
JsonElement root = vector.RootElement;
|
|
JoinAttemptId attemptId = new(Guid.Parse(root.GetProperty("attemptId").GetString()!));
|
|
string authenticator = root.GetProperty("derivedAuthenticator").GetString()!;
|
|
|
|
string ticket = NatIntroductionTokenCodec.Encode(attemptId, authenticator);
|
|
|
|
Assert.Equal(root.GetProperty("connectionTicket").GetString(), ticket);
|
|
Assert.Equal(root.GetProperty("digest").GetString(), NatIntroductionTokenCodec.ComputeDigest(ticket));
|
|
}
|
|
|
|
[Fact]
|
|
public void IntroductionTokenRejectsNonCanonicalOrAlteredFields()
|
|
{
|
|
string valid = NatIntroductionTokenCodec.Encode(
|
|
new JoinAttemptId(Guid.Parse("abcdef00-0000-0000-0000-000000000302")),
|
|
Credential('T'));
|
|
|
|
Assert.False(NatIntroductionTokenCodec.TryDecode(null, out _));
|
|
Assert.False(NatIntroductionTokenCodec.TryDecode(valid[..^1], out _));
|
|
Assert.False(NatIntroductionTokenCodec.TryDecode(valid[..^1] + "!", out _));
|
|
Assert.False(NatIntroductionTokenCodec.TryDecode(new string('A', 43), out _));
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectConnectionRequestRoundTripsFixedBoundedPayloadAndRedactsTicket()
|
|
{
|
|
JoinAttemptId attemptId = new(Guid.Parse("00000000-0000-0000-0000-000000000303"));
|
|
string ticket = Credential('D');
|
|
|
|
byte[] encoded = DirectConnectionRequestCodec.Encode(attemptId, ticket);
|
|
|
|
Assert.Equal(DirectConnectionRequestCodec.EncodedLength, encoded.Length);
|
|
Assert.True(DirectConnectionRequestCodec.TryDecode(encoded, out DirectConnectionRequest? decoded));
|
|
Assert.NotNull(decoded);
|
|
Assert.Equal(attemptId, decoded.AttemptId);
|
|
Assert.Equal(ticket, decoded.ConnectionTicket);
|
|
Assert.DoesNotContain(ticket, decoded.ToString(), StringComparison.Ordinal);
|
|
|
|
encoded[0] ^= 0xff;
|
|
Assert.False(DirectConnectionRequestCodec.TryDecode(encoded, out _));
|
|
Assert.False(DirectConnectionRequestCodec.TryDecode(encoded.AsSpan(1), out _));
|
|
}
|
|
|
|
private static string Credential(char value) => new(value, ContractLimits.DerivedCredentialCharacters);
|
|
}
|