 <p>Why not store the passwords in the database with SHA1, then use HMAC with a client specified key for the communication?</p> <p>Have the server generate a random key and send it with the login request. The client computes the SHA1 hash of the password, then computes the HMAC SHA1 hash of that using the server-specified key. The server then verifies that the result is correct.</p> <p>On the client end:</p> <pre><code>// password is the plaintext password // keyb64 is a random key specified by the server, encoded in base64. string ComputeSecureHash(string password, string keyb64) { byte[] data = Encoding.UTF8.GetBytes(password); byte[] key = Convert.FromBase64String(keyb64); byte[] hash; byte[] machash; // compute a plain SHA1 hash of the specified data using (SHA1Managed sha1 = new SHA1Managed()) { hash = sha1.ComputeHash(data); } // now compute a HMAC hash of that hash, using the random key. using (HMACSHA1 sha1mac = new HMACSHA1(key)) { machash = sha1mac.ComputeHash(hash); } return Convert.ToBase64String(machash); } </code></pre> <p>On the server end:</p> <pre><code>// hash is the string produced by the function above // realHash is the SHA1 hash of the real password, which you've fetched from the db // key is the key you generated for this login session bool VerifyHash(string hash, byte[] realHash, byte[] key) { byte[] machash; using (HMACSHA1 sha1mac = new HMACSHA1(key)) { machash = sha1mac.ComputeHash(realHash); } return (Convert.ToBase64String(machash) == hash); } </code></pre> <p>This allows you to authenticate over a plaintext medium without having the password cracked. </p>