Improve performance using Bcrypt in VertX - java

I'm creating a register method in vertx which use Bcrypt to encode password in database.
My problem came from the slow performance in encoding password using BCrypt.
When im using :
- Bcrypt my query take around ~1200ms
- Whitout Bcrypt ~220ms
So what can i do to improve performance ? Is there antoher way to encode password in VertX ?
i'm using Bcrypt (http://www.mindrot.org/projects/jBCrypt/) in vertx.

As you stated: that's not a Vert.x issue/problem. The BCrypt algorithm takes an X amount of time to encode/encrypt a given value — and it's slow on purpose.
I guess you can leverage on the Vert.x capabilities and have N instances of "worker verticles" doing the encryption work. Again, the time "won't shrink", but you will have "some dedicated guys" just for doing that — you can always tweak the number of instances to your needs. Maybe that's too much, but I'm just throwing it in case you haven't thought about it.
Moreover, I think using BCrypt is (one of) the way(s) to go; it's a one time operation and later on "checking" a given value it is not-so-time-consuming. Additionally, it will give you a better/strong security compared to other (hashing included) algorithms if you use the proper salt size, jadda, jadda.

Note that BCrypt is slow on purpose (see e.g. here: Bcrypt for password hashing because it is slow?) so it is not a "bug" but a feature.
(as mentioned in the link, the slowness adds to extra security - it is slower to brute-force the password)
So you really should think twice before wanting the BCrypt password encryption to be fast.

Honestly, that is probably the best way. BCrypt does a better hash encoding. The faster algorithms aren't nearly as good and certainly don't future proof whatever system you are making. But yes, you can use MD5 and it'll go much faster.

Related

How do I send a password without using String from java to postgresql?

I know that char[] is preferable over String when it comes to passwords, due to the fact that String is immutable. But I have not been able to figure out how to pass it to a prepared statement. Consider this code:
Connection con = MyDBManager.connect();
PreparedStatement stm = con.prepareStatement(
"INSERT INTO my_table(username, password) VALUES(? ?)");
String username = "Jonny";
stm.setString(username);
char[] password = new char[] {'a','b','c','d'};
stm.SetString(password.toString());
It works, but I suspect calling password.toString() defeats the whole purpose of using a char[], so how should I do?
And yes, I know that a password should not be stored in clear text. The password is hashed, but I still want to use the benefits of a char[]
This seemed to work, and I also changed the field in the database from text to bytea and (I think) should in theory give the same benefits as the char[] is supposed to, but I get a strong feeling that I'm not doing it right:
byte[] password = new byte[] {'a','b','c','d'};
stm.SetBytes(password);
Maybe I'm completely wrong in my approach, but my requirements are that the password hash should never exist in an immutable object. I am open to other ways of sending it to the database than PreparedStatement
Answer to comments:
I have learned a lot from #rzwitserloot's answer, but unfortunately it does not help. Never having the password hash in an immutable object is a non-negotiable requirement.
Why are passwords in char[] form?
I know that char[] is preferable over String when it comes to passwords, due to the fact that String is immutable.
If you mean: So now you can't change passwords. That's incorrect.
Perhaps you are referring to the fact that you can't wipe them clean', but just in case you aren't, let me explain that:
There is only one reason that char[] is preferable over String, and it is highly dubious: With a char[], you can 'wipe' the array out. That is, once your process (your java code) no longer needs the password, you can explicitly run Arrays.fill(thePassword, (char) 0); and now RAM no longer contains the password. You can't do this with string - you can null out your reference, but that's just 'wiping out the treasure map'. It's not digging up the treasure and smashing the treasure to bits. Someone willing to dig up the entire beach is still going to find it.
This sounds great, and is the only explanation for why a whole bunch of password-based APIs deal in char[] and not String. HOWEVER, this is extremely dubious as a principle and you should absolutely not rely on it:
If some other process that you cannot trust has access to your process's memory you are quite hosed already. You should fix that at the source, and not try to mitigate this problem by reducing your exposure. That's akin to having a giant gaping hole in your artery and fixing it by hooking up a constant supply of blood bags (fighting symptoms) instead of bandaging the wound (closing the actual hole). If somehow the hole cannot be closed, I guess the symptom fighting is better than nothing, but it's a poor alternative.
You have no actual guarantee, between OS and CPU caches, that wiping out your char array gaurantees that the password is no where in any part of the hardware that a hacker could feasibly get at.
For what it is worth, I would not judge any code that stores strings in passwords as insecure. In fact, I dread code that stores them in char[] form - I fear that the authors will misunderstand the protection that this gives, or that they straight up forget to zero it out: It's making readers of the code make false presumptions (namely, that the password is wiped out, which may not be true, and that this means that the password is not recoverable if anything manages to get a dump of the memory contents, which also probably isn't true).
NB: With security it's a good idea to get into the habit of writing James Bond film scripts. Here's a film script for you:
You run your server in a cloud hosting environment, on a virtualized PC. The operator of this cloud messed up, and upon server deletion (which is really just the termination of a virtual PC running on a host that is running hundreds of PCs), they do not wipe out the memory of the process. Somebody decides to try to abuse this: They ask the cloud hoster to give them a PC with linux on it, they then install a simple app that scans the virtual PC's own memory for anything that looks like a password and reports back, then shuts the machine down and terminates it, and asks for another one.
By using char[] AND wiping out the password, you're more safe against this.. but not if the server just crashes or gets hard-killed _which is exactly how e.g. Amazon EC2 is supposed to be used (see netflix's chaos monkey documentation, which the community at large generally agrees is the right way to do things), in which case there's a risk some password just so happened to be in char[] phase. Not to mention all the other places in memory these can end up in.
See how bond-level scripts help clarify matters? It shows there is SOME point to wiping out char arrays, but it's not foolproof.
How do I store a password in postgres
hashing it is also no good. At least, depending on what you mean with the word 'hash'.
The proper approach involves 2 things:
A 'salt' - the problem is, a LOT of people have iloveyou as a password. It doesn't matter what hashing algorithm you use, hashing algorithms by their nature hash the same input to the same output, so all I need to do if I get a complete dump of your DB is to run SELECT passhash, COUNT(*) AS ct FROM accounts GROUP BY passhash ORDER BY ct DESC LIMIT 1, and voila - that hash? That's iloveyou, and I can then do SELECT username FROM accounts WHERE passhash = ?, and everybody in that list? I can log in as them with pass iloveyou. Simple as that. A salt solves this problem: the idea is, you generate a random number for every account (upon account creation), you then store this random number in the database. The hash you store is the result of hashing the value: CONCATENATE(salt, password). Now every user that is an idiot and uses iloveyou as password ends up with a different hash. To check a password, you take the password as entered, retrieve the salt, recreate CONCAT(salt, pass), hash that, and confirm it matches the DB entry.
You want a hashing algorithm that is slow and weird. SHA-256, for example, is used by bitcoin, so there are a ton of dedicated machines out there that can generate billions of hashes a millisecond for SHA-256, and there's specialized hardware out there (hardware you don't have) that is far faster at it than any computer you own. That's bad, you don't want the hacker to have an advantage. So, you want a hash algo that is really slow, and is not (easily) optimized for custom hardware. BCrypt, SCrypt, and PBKDF are the commonly used variants for this. They're all fine (BCrypt is older and in that sense 'worse', but also simpler and proven. Pick whichever one you want).
Note that most libraries out there will take care of the whole salt business already, no need to explicitly generate and store these (the APIs of these libraries are simply: "Give me a thing to put in a DB for this password" and "The user entered this password, and this is the thing you told me to put in the DB earlier. Is it a match?". 'The thing to put in the DB' contains both the salt and the hash result combined into a single string.
Okay, so how do I get this 'thing to put in DB' that the bcrypt lib gave me to postgres?
It's going over a wire or at least a local socket, into the postgres WAL log, which then goes everywhere. The thing is also literally right there in the DB.
The notion that you can somehow eliminate this hashes value from your system hardware is completely impossible.
So just make a java.lang.String. It's fine.

Java AES with de-hashing

I would like to ask if there is any possibility to do de-hashing with salt.
Because currently I using doing encrypt with salt and hash. But I want to study about de-hashing part, is it possible to do de-hashing ?
I'm assuming that by de-hashing, you mean reversing the hashing process.
Hashing is a form of one way encryption. The original message is entirely destroyed in the process of creating the hash and, therefore, it is not possible to reverse the process. If it is possible, then that is a problem with the hashing algorithm.
Or in more formal terms, Hashing algorithms, by definition, are not Bijective.

Is there a way to guess which algorithm was used to generate hash key?

The input number is 126594 and the output is 66265784-0a82-4ce0-84e4-4d6f791a6970
It has 32 chars, so I tried MD5, but the output is different (http://www.sha1-online.com/).
I am trying to generate the post ID on the project done by another developer and he in unreachable. Also changing everything now would take a lot of time, which we do not have.
The best thing you can do is just try a few different hashing algos. You can use the page you referenced and just try all the different hashing algos they have there.
Actually guessing which hashing function it is based only on the input and hashes is quite hard to do and would probably require much more input-hash-tuples.
It could be MAC+IP address. Generally people use to define it as UUID.
You can try this

why is my pbkdf2 implementation so slow (vs. SQLCipher)?

I have written a simple Android App on my Xoom tablet, which simply stores some string notes in a SQLCipher database.
The user is prompted to type in a passphrase which will be used for the database by the SQLCipher lib. This works fine so far and very smooth.
Now I have also implemented a small PBKDF2 algorithm for authentication purposes
(in fact, i want to encrypt some other files in the future, wich cannot be stored in a database).
But as for now, i only came to check if my pbkdf2 algorithm is correct.
I only used the javax.crypto and java.security libs.
Code snippet as follows:
int derivedKeyLength = 128;
int iterations = 500;
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, iterations, derivedKeyLength);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] derivedKey = f.generateSecret(spec).getEncoded();
The salt is a 16 byte random number, generated with SecureRandom.
So I hardcoded the key and the salt and compare the the derivedKey for authentication (only a test case!)
My Problem now is, that on my Xoom it lasts about 5 seconds until the deriving function is done, although the iteration is set to 500 only.
AFAIK SQLCipher is using an iteration number of 4000 by default, and it responds instant, if the key is wrong or correct.
(if I set the iteration to 4000, it takes at least 15seconds)
The question is, did I implemented that inefficient or is it because SQLCipher is just that good in performance (native NDK functions, etc..)?
Thank you in advance
p.s: sorry, my english isnt that great yet!
Edit:
Sorry, I was not clear enough :-)
I know PBKDF2 is supposed to be slow (in specific the iteration amount, to slow down brute force attacks), thats exactly the reason I am asking! I wanted to set the iteration number to lets say 5000 (which is not acceptable, with over 15seconds)
I'm just wondering because, like I said, SQLCipher also uses PBKDF2 (Iteration = 4k, while I am using 500) for deriving a key from a given password. I'm not talking about the encryption with AES in the end, its only about the difference in deriving the key.
Of course it seems legit that SQLCipher is way faster than an self made keyderiving function, but I did not think that it would be this much difference, since SCLCipher's PBKDF2 really works instant!
Greetings!
OK, that (see below) is not exactly your problem, PBKDF2 is slow but should be nowhere as slow as described with those parameters on that hardware.
There are some stats (and tips) here on Android PBE/KDF performance: http://nelenkov.blogspot.com/2012/04/using-password-based-encryption-on.html . SecretKeyFactory performance problems are not unknown: Any way around awful SecretKeyFactory performance with LVL and AESObfuscator? .
SecretKeyFactory is likely using pure Java implementation. SQLCipher has two relevant features:
it uses OpenSSL, compiled native code (on my desktop OpenSSL's PBKDF2 is nearly 100x faster than
a JVM6 SecretKeyFactory version for 2000 iterations, excluding JVM startup time. I haven't
compared AES speed, it appears other people find it slow on Android too)
the 4000 iteration PBKDF2 is only done on database open, after that there's at most 2 iterations
for the page HMAC secret (assuming the default configuration, as documented)
Your code seems correct, there should not be such a large (linear?) performance degradation when you increase your iterations. The Xoom should be running a non-ancient JVM with JIT, can you verify the performance problem with other code?
PBKDF2 is designed to be slow (see the answer to this question https://security.stackexchange.com/questions/7689/clarification-needed-for-nists-whitepaper-recommendation-for-password-based-ke ) due to the intended key stretching operation. The iteration counter lets you trade off speed for security.
AES was always intended to be fast and is
fast (speed comparison PDF, the chosen AES candidate is referred to by its original name Rijndael in that paper).
I assume you are comparing the PBKDF2 computation time directly to the time taken to perform an SQL operation on your SQLCipher database which will almost certainly have been designed to be fast.
You are effectively comparing two different operations with different requirements, hence the speed difference.
Ok I figured out what the problem was.
If I disconnect the device from my PC it works instant. Also if I reconnect it after that.
Now even with an iteration amount of 5000 and above, the deriving function only needs less than a second!! This is great, since my Xoom isn't the newest of all devices!
May be it is because of the debug mode or something, I don't really know actually!
Anyways, thanks to mr.spuratic. Hope this helps someone in the future :-)

How secure is javax.crypto.Cipher?

I know enough about cryptology to make life difficult for a novice programmer and get laughed at by security experts. So with that in mind, I ask: how secure is javax.crypto.Cipher? I realise that anything can be cracked by someone with a will and a way, but I still would like to know relative details.
The reason I ask is I would like to store account names and passwords that will be sent through my Cryptor class that will encrpyt them, and would like to know if this will do the job. If any one has any literature that I could read, that would be greatly apprieciated.
Thanks ~Aedon
Cipher is a generic class to apply an encryption/decryption algorithm. Its security depends on the actual encryption algorithm used (DES, triple-DES, AES, etc.), on the size of its key, and on the block chaining type that you choose.
If you intend to store passwords securely, then your requirements are quite different from simply "communicating securely/privately". A Cipher on its own is not enough to protect you. You need to use one of these
bcrypt
scrypt
PBKDF2 from PKCS#5
in that circumstance. Here are some arguments and links concerning password security.
The punchline is that "normal" encryption (or hashing, too) is just way too fast to hold off serious attackers. You want to artificially slow down the entire process to make it as hard as possible for somebody systematically attacking your application. A single user won't notice the difference between 1 or 500 milliseconds when entering a password but for an attacker this means that in order to break your scheme it will take them 500 times as long on the average - so if it would have taken roughly 1 month to find a valid password before, now it will take 500 months.
Since NullCipher is a Cipher - not secure at all.

Categories

Resources