/ GUNRPG.Infrastructure / Security / RunValidationResult.cs
RunValidationResult.cs
 1  using System.Security.Cryptography;
 2  
 3  namespace GUNRPG.Security;
 4  
 5  public sealed class RunValidationResult
 6  {
 7      private readonly byte[] _finalStateHash;
 8  
 9      public RunValidationResult(
10          Guid runId,
11          Guid playerId,
12          Guid serverId,
13          byte[] finalStateHash,
14          SignedRunValidation attestation)
15      {
16          RunId = runId;
17          PlayerId = playerId;
18          ServerId = serverId;
19          _finalStateHash = AuthorityCrypto.CloneAndValidateSha256Hash(finalStateHash);
20          if (attestation == null) throw new ArgumentNullException(nameof(attestation));
21          if (attestation.Validation == null)
22              throw new ArgumentException("Attestation Validation must not be null.", nameof(attestation));
23          if (attestation.Certificate == null)
24              throw new ArgumentException("Attestation Certificate must not be null.", nameof(attestation));
25          if (attestation.Validation.RunId != runId)
26              throw new ArgumentException("Attestation RunId does not match RunId.", nameof(attestation));
27          if (attestation.Validation.PlayerId != playerId)
28              throw new ArgumentException("Attestation PlayerId does not match PlayerId.", nameof(attestation));
29          if (attestation.Validation.ServerId != serverId)
30              throw new ArgumentException("Attestation ServerId does not match ServerId.", nameof(attestation));
31          if (attestation.Certificate.ServerId != serverId)
32              throw new ArgumentException("Attestation Certificate ServerId does not match ServerId.", nameof(attestation));
33          if (!CryptographicOperations.FixedTimeEquals(attestation.Validation.FinalStateHash, _finalStateHash))
34              throw new ArgumentException("Attestation FinalStateHash does not match FinalStateHash.", nameof(attestation));
35          Attestation = attestation;
36      }
37  
38      public Guid RunId { get; }
39  
40      public Guid PlayerId { get; }
41  
42      public Guid ServerId { get; }
43  
44      public byte[] FinalStateHash => (byte[])_finalStateHash.Clone();
45  
46      public SignedRunValidation Attestation { get; }
47  
48      public byte[] ComputeResultHash() => ComputeResultHash(this);
49  
50      public static byte[] ComputeResultHash(RunValidationResult result)
51      {
52          ArgumentNullException.ThrowIfNull(result);
53  
54          return ComputeResultHash(
55              result.RunId,
56              result.PlayerId,
57              result.ServerId,
58              result._finalStateHash);
59      }
60  
61      internal static byte[] ComputeResultHash(
62          Guid runId,
63          Guid playerId,
64          Guid serverId,
65          byte[] finalStateHash) =>
66          AuthorityCrypto.ComputeRunResultHash(runId, playerId, serverId, finalStateHash);
67  
68      internal static byte[] ComputeResultHash(RunValidationSignature validation)
69      {
70          ArgumentNullException.ThrowIfNull(validation);
71  
72          return ComputeResultHash(
73              validation.RunId,
74              validation.PlayerId,
75              validation.ServerId,
76              validation.FinalStateHash);
77      }
78  }