/// <summary> /// Loads all methods from interfaces and assigns an identifier /// to each. These are later synchronized with the client. /// </summary> private ServiceInstance CreateMethodMap(int keyIndex, Type serviceType, object service) { var instance = new ServiceInstance() { KeyIndex = keyIndex, InterfaceType = serviceType, InterfaceMethods = new ConcurrentDictionary <int, MethodInfo>(), MethodParametersByRef = new ConcurrentDictionary <int, bool[]>(), SingletonInstance = service }; var currentMethodIdent = 0; if (serviceType.IsInterface) { var methodInfos = serviceType.GetMethods(); foreach (var mi in methodInfos) { instance.InterfaceMethods.TryAdd(currentMethodIdent, mi); var parameterInfos = mi.GetParameters(); var isByRef = new bool[parameterInfos.Length]; for (int i = 0; i < isByRef.Length; i++) { isByRef[i] = parameterInfos[i].ParameterType.IsByRef; } instance.MethodParametersByRef.TryAdd(currentMethodIdent, isByRef); currentMethodIdent++; } } var interfaces = serviceType.GetInterfaces(); foreach (var interfaceType in interfaces) { var methodInfos = interfaceType.GetMethods(); foreach (var mi in methodInfos) { instance.InterfaceMethods.TryAdd(currentMethodIdent, mi); var parameterInfos = mi.GetParameters(); var isByRef = new bool[parameterInfos.Length]; for (int i = 0; i < isByRef.Length; i++) { isByRef[i] = parameterInfos[i].ParameterType.IsByRef; } instance.MethodParametersByRef.TryAdd(currentMethodIdent, isByRef); currentMethodIdent++; } } //Create a list of sync infos from the dictionary var syncSyncInfos = new List <MethodSyncInfo>(); foreach (var kvp in instance.InterfaceMethods) { var parameters = kvp.Value.GetParameters(); var parameterTypes = new string[parameters.Length]; for (var i = 0; i < parameters.Length; i++) { parameterTypes[i] = parameters[i].ParameterType.ToConfigName(); } syncSyncInfos.Add(new MethodSyncInfo { MethodIdent = kvp.Key, MethodName = kvp.Value.Name, MethodReturnType = kvp.Value.ReturnType.ToConfigName(), ParameterTypes = parameterTypes }); } var serviceSyncInfo = new ServiceSyncInfo { ServiceKeyIndex = keyIndex, CompressionThreshold = _compressionThreshold, UseCompression = _useCompression, MethodInfos = syncSyncInfos.ToArray() }; instance.ServiceSyncInfo = serviceSyncInfo; return(instance); }
/// <summary> /// This method asks the server for a list of identifiers paired with method /// names and -parameter types. This is used when invoking methods server side. /// </summary> protected override void SyncInterface(Type serviceType, string username = null, string password = null) { if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) { var sw = Stopwatch.StartNew(); _logger.Debug("Zk authentiation started for: {0}, {1}", username, password); //do zk protocol authentication var sr = new ZkProtocol(); // Step 1. Client sends username and ephemeral hash of random number. var aRand = sr.CryptRand(); var aClientEphemeral = sr.GetClientEphemeralA(aRand); // send username and aClientEphemeral to server _binWriter.Write((int)MessageType.ZkInitiate); _binWriter.Write(username); _logger.Debug("username sent to server: {0}", username); _binWriter.Write(aClientEphemeral); //always 32 bytes _logger.Debug("ClientEphemeral (A) sent to server: {0}", Convert.ToBase64String(aClientEphemeral)); // get response from server var userFound = _binReader.ReadBoolean(); if (!userFound) { _logger.Debug("User not found. InvalidCredentialException thrown."); throw new InvalidCredentialException("authentication failed"); } var salt = _binReader.ReadBytes(32); _logger.Debug("Salt received from server: {0}", Convert.ToBase64String(salt)); var bServerEphemeral = _binReader.ReadBytes(32); _logger.Debug("ServerEphemeral (B) received from server: {0}", Convert.ToBase64String(bServerEphemeral)); // Step 3. Client and server calculate random scramble of ephemeral hash values exchanged. var clientScramble = sr.CalculateRandomScramble(aClientEphemeral, bServerEphemeral); // Step 4. Client computes session key var clientSessionKey = sr.ClientComputeSessionKey(salt, username, password, aClientEphemeral, bServerEphemeral, clientScramble); // Step 6. Client creates hash of session key and sends to server. Server creates same key and verifies. var clientSessionHash = sr.ClientCreateSessionHash(username, salt, aClientEphemeral, bServerEphemeral, clientSessionKey); // send to server and server verifies _binWriter.Write((int)MessageType.ZkProof); _binWriter.Write(clientSessionHash); //always 32 bytes _logger.Debug("ClientSessionKey Hash sent to server: {0}", Convert.ToBase64String(clientSessionHash)); // get response var serverVerified = _binReader.ReadBoolean(); if (!serverVerified) { _logger.Debug("Server verification failed. InvalidCredentialException thrown."); throw new InvalidCredentialException("authentication failed"); } var serverSessionHash = _binReader.ReadBytes(32); var clientServerSessionHash = sr.ServerCreateSessionHash(aClientEphemeral, clientSessionHash, clientSessionKey); if (!serverSessionHash.IsEqualTo(clientServerSessionHash)) { _logger.Debug("Server hash mismatch. InvalidCredentialException thrown. Has received: {0}", Convert.ToBase64String(serverSessionHash)); throw new InvalidCredentialException("authentication failed"); } _logger.Debug("Server Hash match. Received from server: {0}", Convert.ToBase64String(serverSessionHash)); _zkCrypto = new ZkCrypto(clientSessionKey, clientScramble); _logger.Debug("Zk authentiation completed successfully."); sw.Stop(); _stats.Log("ZkAuthentication", sw.ElapsedMilliseconds); } if (!SyncInfoCache.TryGetValue(serviceType, out _syncInfo)) { //write the message type _binWriter.Write((int)MessageType.SyncInterface); if (null != _zkCrypto) { //sync interface with encryption var assemName = serviceType.ToConfigName(); var assemblyNameEncrypted = _zkCrypto.Encrypt(assemName.ConvertToBytes()); _binWriter.Write(assemblyNameEncrypted.Length); _binWriter.Write(assemblyNameEncrypted); } else { _binWriter.Write(serviceType.ToConfigName()); } //read sync data var len = _binReader.ReadInt32(); //len is zero when AssemblyQualifiedName not same version or not found if (len == 0) { throw new TypeAccessException("SyncInterface failed. Type or version of type unknown."); } var bytes = _binReader.ReadBytes(len); if (null != _zkCrypto) { _logger.Debug("Encrypted data received from server: {0}", Convert.ToBase64String(bytes)); bytes = _zkCrypto.Decrypt(bytes); _logger.Debug("Decrypted data received from server: {0}", Convert.ToBase64String(bytes)); } _syncInfo = _serializer.Deserialize <ServiceSyncInfo>(bytes); SyncInfoCache.AddOrUpdate(serviceType, _syncInfo, (t, info) => _syncInfo); } }
/// <summary> /// This method asks the server for a list of identifiers paired with method /// names and -parameter types. This is used when invoking methods server side. /// </summary> protected override void SyncInterface(Type serviceType) { if (!_syncInfoCache.TryGetValue(serviceType, out _syncInfo)) { //write the message type _binWriter.Write((int)MessageType.SyncInterface); _binWriter.Write(serviceType.AssemblyQualifiedName ?? serviceType.FullName); //read sync data var bytes = _binReader.ReadBytes(_binReader.ReadInt32()); _syncInfo = (ServiceSyncInfo)bytes.ToDeserializedObject(); _syncInfoCache.AddOrUpdate(serviceType, _syncInfo, (t, info) => _syncInfo); } }
/// <summary> /// This method asks the server for a list of identifiers paired with method /// names and -parameter types. This is used when invoking methods server side. /// </summary> protected override void SyncInterface(Type serviceType, string username = null, string password = null) { if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) { //do zk protocol authentication var sr = new ZkProtocol(); // Step 1. Client sends username and ephemeral hash of random number. var aRand = sr.CryptRand(); var aClientEphemeral = sr.GetClientEphemeralA(aRand); // send username and aClientEphemeral to server _binWriter.Write((int)MessageType.ZkInitiate); _binWriter.Write(username); _binWriter.Write(aClientEphemeral); //always 32 bytes // get response from server var userFound = _binReader.ReadBoolean(); if (!userFound) { throw new InvalidCredentialException("authentication failed"); } var salt = _binReader.ReadBytes(32); var bServerEphemeral = _binReader.ReadBytes(32); // Step 3. Client and server calculate random scramble of ephemeral hash values exchanged. var clientScramble = sr.CalculateRandomScramble(aClientEphemeral, bServerEphemeral); // Step 4. Client computes session key var clientSessionKey = sr.ClientComputeSessionKey(salt, username, password, aClientEphemeral, bServerEphemeral, clientScramble); // Step 6. Client creates hash of session key and sends to server. Server creates same key and verifies. var clientSessionHash = sr.ClientCreateSessionHash(username, salt, aClientEphemeral, bServerEphemeral, clientSessionKey); // send to server and server verifies _binWriter.Write((int)MessageType.ZkProof); _binWriter.Write(clientSessionHash); //always 32 bytes // get response var serverVerified = _binReader.ReadBoolean(); if (!serverVerified) { throw new InvalidCredentialException("authentication failed"); } var serverSessionHash = _binReader.ReadBytes(32); var clientServerSessionHash = sr.ServerCreateSessionHash(aClientEphemeral, clientSessionHash, clientSessionKey); if (!serverSessionHash.IsEqualTo(clientServerSessionHash)) { throw new InvalidCredentialException("authentication failed"); } _zkCrypto = new ZkCrypto(clientSessionKey, clientScramble); } if (!_syncInfoCache.TryGetValue(serviceType, out _syncInfo)) { //write the message type _binWriter.Write((int)MessageType.SyncInterface); if (null != _zkCrypto) { //sync interface with encryption var assemName = serviceType.FullName; var assemblyNameEncrypted = _zkCrypto.Encrypt(assemName.ConvertToBytes()); _binWriter.Write(assemblyNameEncrypted.Length); _binWriter.Write(assemblyNameEncrypted); } else { _binWriter.Write(serviceType.FullName); } //read sync data var len = _binReader.ReadInt32(); //len is zero when AssemblyQualifiedName not same version or not found #if (!NET35) if (len == 0) throw new TypeAccessException("SyncInterface failed. Type or version of type unknown."); #else if (len == 0) throw new Exception("SyncInterface failed. Type or version of type unknown."); #endif var bytes = _binReader.ReadBytes(len); if (null != _zkCrypto) { bytes = _zkCrypto.Decrypt(bytes); } _syncInfo = bytes.ToDeserializedObject<ServiceSyncInfo>(); _syncInfoCache.AddOrUpdate(serviceType, _syncInfo, (t, info) => _syncInfo); } }
/// <summary> /// This method asks the server for a list of identifiers paired with method /// names and -parameter types. This is used when invoking methods server side. /// </summary> protected override void SyncInterface(Type serviceType, string username = null, string password = null) { if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) { //do zk protocol authentication var sr = new ZkProtocol(); // Step 1. Client sends username and ephemeral hash of random number. var aRand = sr.CryptRand(); var aClientEphemeral = sr.GetClientEphemeralA(aRand); // send username and aClientEphemeral to server _binWriter.Write((int)MessageType.ZkInitiate); _binWriter.Write(username); _binWriter.Write(aClientEphemeral); //always 32 bytes // get response from server var userFound = _binReader.ReadBoolean(); if (!userFound) { throw new InvalidCredentialException("authentication failed"); } var salt = _binReader.ReadBytes(32); var bServerEphemeral = _binReader.ReadBytes(32); // Step 3. Client and server calculate random scramble of ephemeral hash values exchanged. var clientScramble = sr.CalculateRandomScramble(aClientEphemeral, bServerEphemeral); // Step 4. Client computes session key var clientSessionKey = sr.ClientComputeSessionKey(salt, username, password, aClientEphemeral, bServerEphemeral, clientScramble); // Step 6. Client creates hash of session key and sends to server. Server creates same key and verifies. var clientSessionHash = sr.ClientCreateSessionHash(username, salt, aClientEphemeral, bServerEphemeral, clientSessionKey); // send to server and server verifies _binWriter.Write((int)MessageType.ZkProof); _binWriter.Write(clientSessionHash); //always 32 bytes // get response var serverVerified = _binReader.ReadBoolean(); if (!serverVerified) { throw new InvalidCredentialException("authentication failed"); } var serverSessionHash = _binReader.ReadBytes(32); var clientServerSessionHash = sr.ServerCreateSessionHash(aClientEphemeral, clientSessionHash, clientSessionKey); if (!serverSessionHash.IsEqualTo(clientServerSessionHash)) { throw new InvalidCredentialException("authentication failed"); } _zkCrypto = new ZkCrypto(clientSessionKey, clientScramble); } if (!_syncInfoCache.TryGetValue(serviceType, out _syncInfo)) { //write the message type _binWriter.Write((int)MessageType.SyncInterface); if (null != _zkCrypto) { //sync interface with encryption var assemName = serviceType.FullName; var assemblyNameEncrypted = _zkCrypto.Encrypt(assemName.ConvertToBytes()); _binWriter.Write(assemblyNameEncrypted.Length); _binWriter.Write(assemblyNameEncrypted); } else { _binWriter.Write(serviceType.FullName); } //read sync data var len = _binReader.ReadInt32(); //len is zero when AssemblyQualifiedName not same version or not found #if (!NET35) if (len == 0) { throw new TypeAccessException("SyncInterface failed. Type or version of type unknown."); } #else if (len == 0) { throw new Exception("SyncInterface failed. Type or version of type unknown."); } #endif var bytes = _binReader.ReadBytes(len); if (null != _zkCrypto) { bytes = _zkCrypto.Decrypt(bytes); } _syncInfo = bytes.ToDeserializedObject <ServiceSyncInfo>(); _syncInfoCache.AddOrUpdate(serviceType, _syncInfo, (t, info) => _syncInfo); } }