bcrypt usage

Started by
30 comments, last by rip-off 12 years, 9 months ago
What's the usage of bcrypt? I was using the HashPassword method but it's returning a different hash value every time for the same string. I'm using the .NET implementation but I'm guessing it's all the same method wise on how you would do this.
Advertisement
Show us your code. How are you generating/storing the salt? Which implementation of BCrypt are you using, some light Googling suggests it isn't included with .Net.
It's not a native .NET library that I'm using. I think the salt thing was confusing me. I was under the impression I didn't have to have a salt, but it looks like I do. So that would mean I have to send the salt from the server to the client in order for the client to use bcrypt on their password and get the same exact value.

It seems dangerous to send the salt to the client because I have to do that just based on their username since the reason for sending them the salt is to they can bcrypt the pw on their side and then send that bcrypted pw back to the server to validate. So someone could get the salts of anyone pending they know their username. I thought it might be more like other hashes where you aren't required to have a salt.

Maybe sending the salt just based on username alone isn't that big of a deal?
Step back, lets look at this from a different perspective. What problems are you trying to solve?

Server side hashing and salting solves the problem where the user database is compromised, making it much harder for an attacker to reverse the hashes back into plaintext for use in other services.

Client side hashing solves the problem of someone sniffing the passoword on the wire, but only when used in "challenge/response" schemes. This cannot really be used with the above, because the server needs to do the same steps as the client, which means that the client needs to know the salt or the server needs to know the plaintext.

Sending the salt when given the user name effectively allows an attacker to remotely determine whether users exist, which may be bad enough from a privacy standpoint, but if the user name is an email address could easily lend itself to a phising campaign against your users.

A standard solution to the above problems is to send the plaintext password to the server across an encypted channel, and then use the standard salted/hashed user database on the server side.
Yeah that makes sense. I guess if a salt wasn't required that's what could be stored in the DB and the same hash could be done on the client and the username and hashed pw could be sent over to the server at the same time. I know the salt makes it harder to break but from my understanding of bcrypt the algorithm itself (without the salt even) makes it hard to break because it would be so time consuming that it wouldn't even be worth trying. My main concern is that I'm using a very simple sockets library built on top of .NET sockets, but I don't have access to any of the underlying socket information. It basically gives you events for when connected, disconnected, data arrived, etc. Then has methods like SendToAll(), SendToClient(), SendToServer(). It's very simple and amazingly easy to use (I've tried working with .NET sockets in an async mode and it's a pain. I want to focus on my game messages not the networking technology). So that being said I would have no idea how to or if I even could encrypt data going over via SSL (as I assume that would be the preferred method) with this library.

This networking library basically has you send a byte type to signify the msg and the "packet" data is just a string. I'm using this for lobby stuff for my game via .NET forms so I just csv values in the "packet". I created a BitStream class (much like RakNet which I know and love but getting it to work in .NET is a nightmare) but it just helps break out and write the csv string "packet". I'm doing this because using .NET GUI is much easier than making my own and the graphics library I'm using doesn't have one (Leadwerks). So the lobby area which is basically viewing matches, chatting, and changing some data about your "team" is done in this .NET GUI and when you start a "match" it launches a separate exe that is my actual game (done with Leadwerks). Passed to this exe will be a session id that is sent to the client from the server, and a "match" id that is also sent from server to client (thinking possibly IP address also to help avoid chances of spoofing). This actual game exe is going to use RakNet and Leadwerks in C++ and will connect to the game server (as opposed to the lobby server), validate session id against match id (which is stored in a DB on the server side, which was setup from the lobby) and then start playing the game.

So I guess a question would be, if bcrypt without a salt is still very time consuming to break (years from what I'm reading), then couldn't I just hardcode a salt value so that I can run bcrypt on the client side with this hardcoded salt value (basically making the salt useless but my thinking is bcrypt without salt is still years to break with brute force)? That way I don't have to send any salt to the client and that removes the phising possibility.

How much is being compromised by removing the salt factor in bcrypt seeing as the algorithm speed alone seems to be the key with bcrypt anyway. I've read some stuff about it possibly taking 12 years to brute force a bcrypt hashed value. So would removing the salt make that 6 years then (or something like that)?
You can build an encrypted channel over such a system. A simple solution is to hard code the server's public key into the client. The client generates a (new, random) session symmetric key, and encrypts the password with this. It then encrypts the session key with the server's public key, and sends the two encrypted values to the server. The server can decrypt the session key, and then can then use this to decrypt the password. I wouldn't recommend this approach, only as a last resort, as you're effectively re-implementing parts of SSL. One bug could render your entire scheme useless.

I don't understand why you need to use this library you are talking about though. The lobby client probably doesn't need async networking. If you use standard HTTP for the lobby commications, you can use built in methods (e.g. WebClient). You can also avoid writing complex custom server socket code, you can use a pre-written HTTP server and something like PHP for handling the requests. This will probably scale far better than writing this yourself. It will likely be cheaper to host too.

So I guess a question would be, if bcrypt without a salt is still very time consuming to break (years from what I'm reading), then couldn't I just hardcode a salt value so that I can run bcrypt on the client side with this hardcoded salt value (basically making the salt useless but my thinking is bcrypt without salt is still years to break with brute force)? That way I don't have to send any salt to the client and that removes the phising possibility.
[/quote]
I'm sitting next to you as you login. You type in your password, and then bcrypt() it. You send the resulting hash to the server. My computer is listening for network activity, and records your username and the bcrypted password. I can now access your account by sending the username and bcrypted password to the server at any time. I don't need to know your password, effectively the bcrypted password is the password.

The only advantage of this proposed scheme over sending the raw password is that I cannot directly use the hash to try login to other services where you might be using the same username/password.

There are two ways to mitigate this type of attack. One is to use a challenge-response protocol, the other is to encrypt the password. You could design a challenge response protocol where the client sends the username, you send the salt and a nonce to the client, which generates H(nonce, H(salt, password)). The server can verify this. As mentioned, this could lead to information disclosure about user names, and also potentially to phishing.

I'm sitting next to you as you login. You type in your password, and then bcrypt() it. You send the resulting hash to the server. My computer is listening for network activity, and records your username and the bcrypted password. I can now access your account by sending the username and bcrypted password to the server at any time. I don't need to know your password, effectively the bcrypted password is the password.
[/quote]

I bcrypt the password twice (not sure if I mentioned that). I bcrypt just the pw, then I bcrypt that result with the session id that the server sends to the clients and is client specific and managed on the server. So the value I send over the wire is the bcrypt of the pw bcrypt'd with that result + session id (which changes every logon). What's stored in the DB is just the bcrypt of the original pw. Once I get the bcrypt pw + session from the client I do the same on the server since the server knows the session id of the calling client and can get the original bcrypt of the pw from the DB. The library I'm using actually sends that session id (Guid) as one of the parameters of the Data Received method so it's nice and simple to manage. I guess in that sense the session id (which is given on connect but not authorized) is acting as a salt. The difference being it changes on every logon.

So the process would go as:

1) Client does a connect to server
2) Server says I accept the connection but you aren't authorized to do anything yet
3) Client gets an event that says they are connected and asks for a session id
4) Server sends them a session id
5) Client bcrypt's their pw, then bcrypt's that result combined with the session id (the session id basically acting as a salt at this point) and sends that along with username
6) Server queries the DB on username, gets the bcrypt password, bcrypts that value + this clients session id to validate the 2 match and if so flags this client as authenticated on the server side. Future calls from this client send their session id (automatically from this sockets library) and everything they do in the lobby will check to see if they have been authorized.

(This is what I currently have implemented and working, but I just wanted to talk through the security of it)

So this seems safe as even if you were on the wire you wouldn't see the original bcrypt'd pw because that was bcrypted with a session id that changes on every logon. Spoofing the current session would be possible but not logging on at a time of the hackers choosing. I would think this would be plenty safe as most of these mid man attacks are probably not live attacks since they aren't going to sit and wait for hours/days waiting for you to log on. Even if they got some kind of notice the only thing they could do is mess with your current session of game data and this seems like an unlikely/uncommon problem and is not at least a major security risk on their overall personal data but just might mess with their video game data.


I don't understand why you need to use this library you are talking about though. The lobby client probably doesn't need async networking. If you use standard HTTP for the lobby commications, you can use built in methods (e.g. WebClient). You can also avoid writing complex custom server socket code, you can use a pre-written HTTP server and something like PHP for handling the requests. This will probably scale far better than writing this yourself. It will likely be cheaper to host too.
[/quote]

I don't have much experience working with http or PHP or any other web stuff. All my networking experience is with RakNet or other UDP/TCP libraries and sending/processing custom messages.
Well, you should really have described this earlier, the scheme you are talking about now is considerably different from the one I thought you might be doing.

By losing the salt, you lose one key feature of these algorithms. I can generate a table of common/weak passwords -> bcrypt hashes. When I see the protocol on the wire, I can brute force your password if it is weak by simply going through the hashes in the table, hashing them with the session identifier. There are also concerns about how the session identifier is generated. If it isn't designed to be secure, there is a risk in depending on it in your authentication protocol.


I don't have much experience working with http or PHP or any other web stuff.
[/quote]
It is fairly easy. Arguably, it is easier and more secure than trying to write this yourself.

However, the point even stands without using these technologies. Your client shouldn't need async sockets, it could create a simple SSL socket. The server needs to be a little smarter if you expect high load. The great thing about defining your algorithm without depending on this library means that you could start out with a really simple .Net SSL server, and then move to something more advanced like an async version or a Node.js implementation as your load increases.

It is fairly easy. Arguably, it is easier and more secure than trying to write this yourself.
[/quote]

I've done 1 of these at work and it required a certificate to be installed on our server machine. Is there ways to not require this? I've never played a game where it required me to install any kind of certificate so it could authenticate.


Your client shouldn't need async sockets
[/quote]

But I can't have it blocking the UI, and it would be nice to avoid threads because I've had nothing but a pain updating a UI element from another thread. So I guess that's why the library I'm using was just nice because the events all fired in the UI thread and all that behind the scenes stuff was handled for me. I'm not sure how this normally would work otherwise with the SSL synchronous way.

I found http://msdn.microsof....sslstream.aspx example that looks to be what you are talking about. It's using a synchronous SSL TCP/IP connection. In this case the cert needs to be installed on the machine. At my work there is a couple processes where we actually load the cert via code from the .cert file path, which I suspect would be easier for the users, but I would have to ask, are games really doing this?

I suppose I could actually just do this for sign on and then go back to my other library (because honestly this other library is so much easier to use then sockets directly or even the TcpClient class in .NET), and in that case it could be blocking as no need to update the UI in the few seconds it's checking credentials.

With this library below is all I have to do. The library is http://code.google.c...twork-library/. It's older and doesn't look like it's being updated anymore which is a shame because on the todo list was "Dynamic automated encryption and decryption transparent to your code" . That would have been nice :)


client = new clsClient();

client.Connected += new clsClient.ConnectedEventHandler(client_Connected);
client.Disconnected += new clsClient.DisconnectedEventHandler(client_Disconnected);
client.PacketReceived += new clsClient.PacketReceivedEventHandler(client_PacketReceived);
client.Connect("127.0.0.1", "5000", false);

void client_PacketReceived(byte PacketType, string Packet)
{
}
void client_Disconnected()
{
}
void client_Connected()
{
}


That compared to MS's example of reading data from the TcpClient class. In my view there is just no comparison in complexity. And the below code isn't even async. The complexity of adding that is even worse.

http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx

There are two ways to mitigate this type of attack. One is to use a challenge-response protocol, the other is to encrypt the password. You could design a challenge response protocol where the client sends the username, you send the salt and a nonce to the client, which generates H(nonce, H(salt, password)). The server can verify this. As mentioned, this could lead to information disclosure about user names, and also potentially to phishing.


It's worth pointing out that this is a bit redundant. You're already sending a nonce, so why are you sending another value (a nonce?) (and calling it a "salt") with it? Having the server send just a nonce, and have the client send back H(nonce, password) is what would make sense if not for the fact that it is a bad idea on an unencrypted channel for other reasons: Consider a third-party listening in. The third-party can see (nonce, H(nonce, password)) pairs. This is equivalent to a web server leaking its password database. If the algorithm H is in fact bcrypt, the attacker can crack a smallish percentage of passwords. (I would call it a "large" percentage.) (Of course, if the algorithm H is HMAC-SHA-256 or something, the attacker can crack a larger percentage.) So if you did use such a scheme you'd also want this to be over an already-secured channel. But once you've got that set up, just have the client send the password.

[quote=rpiller]I've done 1 of these at work and it required a certificate to be installed on our server machine. Is there ways to not require this? I've never played a game where it required me to install any kind of certificate so it could authenticate.[/quote]

This doesn't seem like a problem. You can generate a certificate yourself, and it can be self-signed, since the client can have the public certificate pre-distributed or just as a special case accept a certificate with a particular fingerprint.

This topic is closed to new replies.

Advertisement