#define TRACE using System; using System.Diagnostics; using System.Globalization; using System.Numerics; using System.Security.Cryptography; using System.Text; using ArchestrAServices.Common; namespace ArchestrAServices.Contract; public class ServiceAuthentication : EncryptionBase { private RNGCryptoServiceProvider m_Random = new RNGCryptoServiceProvider(); public ConnectionId connectionId { get; private set; } public bool SecureSessionEstablished { get; private set; } public string ReasonSecureSessionNotEstablished { get; private set; } public BigInteger ClientPublicKey { get; private set; } public BigInteger ServicePrivateKey { get; private set; } public BigInteger ServicePublicKey { get; private set; } public ServiceAuthentication() { Reset(); ReasonSecureSessionNotEstablished = "Constructed"; base.DH_passphrase = Constants.GetDHPassphrase(); base.hashAlgorithm = Constants.hashAlgorithm; } public ArchestrAResult ProcessClientConnection(string application, string domain, string host, PublicKey ClientToken, out Connection connectionDescription) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, string.Format(CultureInfo.CurrentCulture, "SvcAuth: Processing client Connect() call '{0}', '{1}', '{2}'", new object[3] { application, domain, host })); connectionId = new ConnectionId { Id = Guid.NewGuid() }; ClientPublicKey = new BigInteger(ClientToken.KeyValue); Constants.GenerateKey(Constants.DH_KeySize, out DH_p, out DH_g); BigInteger bigInteger = DH_p - new BigInteger(1); ServicePrivateKey = new BigInteger(0); while (ServicePrivateKey >= bigInteger || ServicePrivateKey <= 0L) { byte[] array = new byte[Constants.DH_SecretSize / 8]; m_Random.GetBytes(array); ServicePrivateKey = new BigInteger(array); } ServicePublicKey = BigInteger.ModPow(DH_g, ServicePrivateKey, DH_p); base.NegotiatedKey = Encoding.UTF8.GetBytes(base.DH_passphrase); connectionDescription = default(Connection); connectionDescription.idField = connectionId; connectionDescription.serviceKeyField.ApplicationName = application; connectionDescription.serviceKeyField.DomainName = domain; connectionDescription.serviceKeyField.HostName = host; connectionDescription.serviceKeyField.KeyValue = ServicePublicKey.ToByteArray(); SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, string.Format(CultureInfo.CurrentCulture, "SvcAuth: Captured {0}-bit client public key, generated {1}-bit service public key, computed {2}-bit negotiated private key", new object[3] { ClientToken.KeyValue.Length * 8, connectionDescription.serviceKeyField.KeyValue.Length * 8, base.NegotiatedKey.Length * 8 })); byte[] array2 = ServicePublicKey.ToByteArray(); byte[] array3 = ClientPublicKey.ToByteArray(); byte[] array4 = new byte[array2.Length + array3.Length + 2]; int num = array4.Length - 2; array4[0] = (byte)((ulong)num & 0xFFuL); array4[1] = (byte)(((ulong)num >> 8) & 0xFF); Array.Copy(array2, 0, array4, 2, array2.Length); Array.Copy(array3, 0, array4, array2.Length + 2, array3.Length); byte[] bytes = Encoding.UTF8.GetBytes(base.DH_passphrase); byte[] array5 = Encrypt(array4, bytes); byte[] array6 = new byte[array5.Length + 2]; int num2 = array6.Length - 2; array6[0] = (byte)((ulong)num2 & 0xFFuL); array6[1] = (byte)(((ulong)num2 >> 8) & 0xFF); Array.Copy(array5, 0, array6, 2, array5.Length); byte[] array7 = Encrypt(array6, base.NegotiatedKey); connectionDescription.authenticationDataField.AuthenticationData = array7; SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, string.Format(CultureInfo.CurrentCulture, "SvcAuth: Generated {0}-bit service validation data, returning to client", new object[1] { array7.Length * 8 })); return ResultFactory.MakeGoodResult(); } public ArchestrAResult ProcessClientActivate(ConnectionId Id, ConnectionAuthenticationData Authentication, ulong Timeout) { if (Id.Id != connectionId.Id) { SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, "SvcAuth: Client called ActivateSession() with invalid connection ID, no secure session created"); Reset(); ReasonSecureSessionNotEstablished = "ProcessClientActivate called with bad connection id"; return ResultFactory.MakeResult(ArchestrAError.ApplicationAuthenticationError, 0); } byte[] array = ClientPublicKey.ToByteArray(); byte[] array2 = ServicePublicKey.ToByteArray(); byte[] array3 = new byte[array.Length + array2.Length]; Array.Copy(array, array3, array.Length); Array.Copy(array2, 0, array3, array.Length, array2.Length); byte[] array4 = Decrypt(Authentication.AuthenticationData, base.NegotiatedKey); byte[] array5 = new byte[array4[0] + (array4[1] << 8)]; for (int i = 0; i < array5.Length; i++) { array5[i] = 0; } Array.Copy(array4, 2, array5, 0, array4.Length - 2); byte[] bytes = Encoding.UTF8.GetBytes(base.DH_passphrase); byte[] array6 = Decrypt(array5, bytes); byte[] array7 = new byte[array6[0] + (array6[1] << 8)]; for (int j = 0; j < array7.Length; j++) { array7[j] = 0; } Array.Copy(array6, 2, array7, 0, array6.Length - 2); bool flag = array3.Length == array7.Length; if (flag) { for (int k = 0; k < array7.Length; k++) { if (array3[k] != array7[k]) { flag = false; break; } } } ArchestrAResult result = ResultFactory.MakeGoodResult(); if (flag) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, string.Format(CultureInfo.CurrentCulture, "SvcAuth: Confirmed {0}-bit client validation data, secure session established", new object[1] { array7.Length * 8 })); SecureSessionEstablished = true; ReasonSecureSessionNotEstablished = "Secure session established"; } else { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, string.Format(CultureInfo.CurrentCulture, "SvcAuth: Could not confirm {0}-bit client validation data, secure session not established", new object[1] { array7.Length * 8 })); SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, string.Format(CultureInfo.CurrentCulture, "SvcAuth: Could not confirm {0}-bit client validation data, secure session not established", new object[1] { array7.Length * 8 })); SecureSessionEstablished = false; ReasonSecureSessionNotEstablished = "Client validation payload incorrect"; result = ResultFactory.MakeResult(ArchestrAError.ApplicationAuthenticationError, 0); } return result; } public ArchestrAResult ProcessClientDisconnect(ConnectionId Id) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SvcAuth: Processing Disconnect() call from client"); Reset(); ReasonSecureSessionNotEstablished = "Client disconnected"; return ResultFactory.MakeGoodResult(); } private void Reset() { connectionId = new ConnectionId { Id = default(Guid) }; SecureSessionEstablished = false; ReasonSecureSessionNotEstablished = "Reset"; ClientPublicKey = BigInteger.Zero; ServicePrivateKey = BigInteger.MinusOne; ServicePublicKey = BigInteger.Zero; base.NegotiatedKey = new byte[200]; m_Random.GetBytes(base.NegotiatedKey); } }