Easy C++ BCrypt library

Started by
16 comments, last by rpiller 11 years, 3 months ago

I can't seem to find a good BCrypt library that's simple and cross-platform for C++. Anyone have any suggestions? Has anyone made any wrappers to any? On the website where players sign up for my game (which is .NET) I use http://bcrypt.codeplex.com/, which is so simple to use. I'm sort of looking for something to match this for my game client (which is in C++) so it can do the same when it bcrypt's the PW on the client and sends to the server for login validation.

I'm using RakNet for my networking and this login will be done over a secure connection, but I also want this extra layer because I don't want to store the actual PW of players on my server but instead the bcrypt'd value in case the DB becomes compromised in the future. I'll encrypt the DB field also, but this is just another layer of protection. Those 3 layers (secure connection, bcrypt pw, encrypted DB field) I would think would think would be enough protection.

Advertisement

I believe openssl crypto module (http://www.openssl.org/docs/crypto/crypto.html) implements all you need. It is written in C, not CPP, but I believe you can easily warp it in a class, if you need some OOP feature.

Also, are you set in stone for this method?

The method I am using is (register):

1) Generate a random number.

2) Decrypt the password received by the client

3) Calculate a hash using the password and the random number

4) Save on the DB the random number (step 1) and the hash (step 3).

To authenticate:

1) Decrypt the password received by the client

2) Calculate the hash using the random number saved on database.

3) Check if saved hash match with the one I just calculated.

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

I'll check that out thanks.

We are basically doing the same thing, but from everything I've read using a normal hash is bad practice as they are normally built for speed, which means most hackers can brute force them. BCrypt is slow on purpose and the speed can be changed with the increased speed of computers. I'm not sure if the "hash" in your flow is via BCrypt or not. Also I'm just adding another layer with the secure connection (RakNet basically does this for me, and encrypt the DB field which MySQL basically does for me), so it doesn't add that much overhead.

[quote name='KnolanCross' timestamp='1357251120' post='5017271']
1) Generate a random number.
2) Decrypt the password received by the client
3) Calculate a hash using the password and the random number
4) Save on the DB the random number (step 1) and the hash (step 3).

To authenticate:
1) Decrypt the password received by the client
2) Calculate the hash using the random number saved on database.
3) Check if saved hash match with the one I just calculated.
[/quote]

Uh, I hope you are using SSL/TLS or something similar to transmit password information securely, otherwise this is vulnerable to a replay attack.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

1) Generate a random number.
2) Decrypt the password received by the client
3) Calculate a hash using the password and the random number
4) Save on the DB the random number (step 1) and the hash (step 3).

To authenticate:
1) Decrypt the password received by the client
2) Calculate the hash using the random number saved on database.
3) Check if saved hash match with the one I just calculated.

Uh, I hope you are using SSL/TLS or something similar to transmit password information securely, otherwise this is vulnerable to a replay attack.

Since he said he is using a safe conection, I didn't clarify this part. But yes, I am, RSA (2048 bits key) with PKCS#1 v1.5 to be more exactly.

On hashes, depends on the algorithm you are using. For instance, MD5 has been broken, but SHA2 and SHA3 haven't (link: http://en.wikipedia.org/wiki/Sha512)

EDIT:

In case anyone in the future is interessed using the python lib, here is the link to its documentation:

http://packages.python.org/pycrypto/

And the package, current versions as of the date of this post:

http://pypi.python.org/pypi/pycrypto/2.6

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

For instance, MD5 has been broken, but SHA2 and SHA3 haven't

I don't think it's about the breaking of the hash algo as a brute force hack isn't breaking anything, it's simply using computer power to try many combinations. Since it is my understanding that SHA2 & SHA3 are still fast algorithms hackers can brute force "really" fast. The faster the hardware gets over time the easier it is to brute force these fast hash algorithms. Look at this article: http://hackaday.com/2012/12/06/25-gpus-brute-force-348-billion-hashes-per-second-to-crack-your-passwords/

348 billions hashes per second!!! Fast hashing algo's just shouldn't be used for passwords, because the speed can always get faster which means the PW's can get hacked easier. I use BCrypt because you can control the speed of the algo, and can change it over time to keep up with the speed of computers.

Again, this is all my limited understanding of this space as it's a big and complicated space :)

Even at that speed he would still take 2 years to calculate all the possible hashs. The main point of any cryptography search space is that it grows exponentially, while the attacker's power grows linearly.

Still, assuming he can "break" the hash by bruteforce in some fast way, he will only find the random number operated with the password, not the password itself (which is useless).

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

Even at that speed he would still take 2 years to calculate all the possible hashs. The main point of any cryptography search space is that it grows exponentially, while the attacker's power grows linearly.

Still, assuming he can "break" the hash by bruteforce in some fast way, he will only find the random number operated with the password, not the password itself (which is useless).

If the attacker doesn't have access to your database, then it's fine. But if he does, then he has access to this random number, and can mount a standard brute-force attack on the password space, which is considerably smaller than the hash's entire search space, this is why you want a slow hashing function in case your database is compromised (and yes, saying "this will never happen" is an easy way to be sorry later on).

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

I still don't understand why the client needs to calculate the bcrypt.

If you receive bcrypt(password) from the client, and compare to stored(bcrypt(password)) on the server, then the token you store on the server, if it is leaked, is enough to gain access, and in effect becomes the plain-text password for an attacker.
enum Bool { True, False, FileNotFound };

I guess I view it as an extra layer of security when sending the password across the wire. If the wire gets hacked into at least they won't see the plaintext password since the player could be using that for other sites. If someone is able to hack the wire (even if it's thought to be unhackable today) at least it'll only be the hashed value for just this game. I view it as minimizing the already minimal risk and it doesn't introduce that much more work on my part. smile.png

If the wire is truly unhackable then no harm done, just minimal extra work.

then the token you store on the server

What "token" are you referring too? The only thing on the server would be the MySQL encrypted column that holds the salt & hashed pw by user. If those are leaked then they have to decrypt the data first. If that's done then there isn't much you can do anyway for this game, but at least it's not plain text for them to try with other sites for the user.

This topic is closed to new replies.

Advertisement