ServerIdentity.cs
1 using System.Security.Cryptography; 2 3 namespace GUNRPG.Security; 4 5 public sealed class ServerIdentity 6 { 7 private readonly byte[] _serverPrivateKey; 8 9 public ServerIdentity(ServerCertificate certificate, byte[] serverPrivateKey) 10 { 11 ArgumentNullException.ThrowIfNull(certificate); 12 13 var normalizedPrivateKey = AuthorityCrypto.CloneAndValidatePrivateKey(serverPrivateKey); 14 var derivedPublicKey = AuthorityCrypto.GetPublicKey(normalizedPrivateKey); 15 var certificatePublicKey = certificate.PublicKey; 16 if (!CryptographicOperations.FixedTimeEquals(derivedPublicKey, certificatePublicKey)) 17 { 18 throw new ArgumentException("The supplied private key does not match the certificate public key.", nameof(serverPrivateKey)); 19 } 20 21 Certificate = certificate; 22 _serverPrivateKey = normalizedPrivateKey; 23 } 24 25 public ServerCertificate Certificate { get; } 26 27 public RunValidationSignature SignRunValidation( 28 Guid runId, 29 Guid playerId, 30 byte[] finalStateHash) 31 { 32 var payloadHash = AuthorityCrypto.ComputeRunValidationPayloadHash(runId, playerId, finalStateHash); 33 var signature = AuthorityCrypto.SignHashedPayload(_serverPrivateKey, payloadHash); 34 return new RunValidationSignature(runId, playerId, finalStateHash, Certificate.ServerId, signature); 35 } 36 37 public SignedRunValidation SignSignedRunValidation(Guid runId, Guid playerId, byte[] finalStateHash) => 38 new(SignRunValidation(runId, playerId, finalStateHash), Certificate); 39 40 public static byte[] GeneratePrivateKey() => AuthorityCrypto.GeneratePrivateKey(); 41 42 public static byte[] GetPublicKey(byte[] privateKey) => AuthorityCrypto.GetPublicKey(privateKey); 43 }