public bool ProcessZkInitiation(BinaryReader binReader, BinaryWriter binWriter, Stopwatch sw) { _username = binReader.ReadString(); _aEphemeral = binReader.ReadBytes(32); _logger.Debug("ZkInitiation client username received: {0}", _username); _logger.Debug("ZkInitiation client Ephemeral received: {0}", Convert.ToBase64String(_aEphemeral)); _zkPasswordHash = _repository.GetPasswordHashSet(_username); if (null == _zkPasswordHash) { _logger.Debug("ZkInitiation client username not found. Authentication failed."); binWriter.Write(false); return(false); } _bRand = _zkProtocol.CryptRand(); _bEphemeral = _zkProtocol.GetServerEphemeralB(_zkPasswordHash.Salt, _zkPasswordHash.Verifier, _bRand); _scramble = _zkProtocol.CalculateRandomScramble(_aEphemeral, _bEphemeral); _serverSessionKey = _zkProtocol.ServerComputeSessionKey(_zkPasswordHash.Salt, _zkPasswordHash.Key, _aEphemeral, _bEphemeral, _scramble); binWriter.Write(true); binWriter.Write(_zkPasswordHash.Salt); _logger.Debug("ZkInitiation hash salt sent to client: {0}", Convert.ToBase64String(_zkPasswordHash.Salt)); binWriter.Write(_bEphemeral); _logger.Debug("ZkInitiation server Ephemeral sent to client: {0}", Convert.ToBase64String(_bEphemeral)); return(true); }
public bool ProcessZkInitiation(BinaryReader binReader, BinaryWriter binWriter, Stopwatch sw) { _username = binReader.ReadString(); _aEphemeral = binReader.ReadBytes(32); _zkPasswordHash = _repository.GetPasswordHashSet(_username); if (null == _zkPasswordHash) { binWriter.Write(false); return(false); } _bRand = _zkProtocol.CryptRand(); _bEphemeral = _zkProtocol.GetServerEphemeralB(_zkPasswordHash.Salt, _zkPasswordHash.Verifier, _bRand); _scramble = _zkProtocol.CalculateRandomScramble(_aEphemeral, _bEphemeral); _serverSessionKey = _zkProtocol.ServerComputeSessionKey(_zkPasswordHash.Salt, _zkPasswordHash.Key, _aEphemeral, _bEphemeral, _scramble); binWriter.Write(true); binWriter.Write(_zkPasswordHash.Salt); binWriter.Write(_bEphemeral); return(true); }
/// <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); } }
public void SimpleProtocolTest() { var sr = new ZkProtocol(); var username = "******"; var pwd = "cc3a6a12-0e5b-47fb-ae45-3485e34582d4"; // prerequisit: generate password hash that would be stored on server var pwdHash = sr.HashCredentials(username, pwd); // 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 // Step 2. Server looks up username, gets pwd hash, and sends client ephemeral has of params. var bRand = sr.CryptRand(); var bServerEphemeral = sr.GetServerEphemeralB(pwdHash.Salt, pwdHash.Verifier, bRand); // send salt and bServerEphemeral to client var clientSalt = pwdHash.Salt; // Step 3. Client and server calculate random scramble of ephemeral hash values exchanged. var clientScramble = sr.CalculateRandomScramble(aClientEphemeral, bServerEphemeral); var serverScramble = sr.CalculateRandomScramble(aClientEphemeral, bServerEphemeral); var scrambleSame = clientScramble.IsEqualTo(serverScramble); // Step 4. Client computes session key var clientSessionKey = sr.ClientComputeSessionKey(clientSalt, username, pwd, aClientEphemeral, bServerEphemeral, clientScramble); // Step 5. Server computes session key var serverSessionKey = sr.ServerComputeSessionKey(pwdHash.Salt, pwdHash.Key, aClientEphemeral, bServerEphemeral, serverScramble); var sessionKeysSame = clientSessionKey.IsEqualTo(serverSessionKey); // Step 6. Client creates hash of session key and sends to server. Server creates same key and verifies. var clientSessionHash = sr.ClientCreateSessionHash(username, pwdHash.Salt, aClientEphemeral, bServerEphemeral, clientSessionKey); // send to server and server verifies // server validates clientSessionHash is same as serverClientSessionHash var serverClientSessionHash = sr.ClientCreateSessionHash(username, pwdHash.Salt, aClientEphemeral, bServerEphemeral, serverSessionKey); var clientEqualToServer = clientSessionHash.IsEqualTo(serverClientSessionHash); // Step 7. Server creates hash of session key and sends to client. Client creates same key and verifies. var serverSessionHash = sr.ServerCreateSessionHash(aClientEphemeral, clientSessionHash, serverSessionKey); // server sends serverSessionHash to client // validate that serverSessionHash is same as clientServerSessionHash var clientServerSessionHash = sr.ServerCreateSessionHash(aClientEphemeral, clientSessionHash, clientSessionKey); var serverEqualToClient = serverSessionHash.IsEqualTo(clientServerSessionHash); //proof Assert.IsTrue(sessionKeysSame); Assert.IsTrue(scrambleSame); Assert.IsTrue(clientEqualToServer); Assert.IsTrue(serverEqualToClient); var data = sr.Combine(sr.CryptRand(), sr.CryptRand(), sr.CryptRand()); var crypto = new ZkCrypto(clientSessionKey, clientScramble); var encrypted = crypto.Encrypt(data); var decrypted = crypto.Decrypt(encrypted); var cryptSame = data.IsEqualTo(decrypted); Assert.IsTrue(cryptSame); }