I am currently trying to modify an existing GWT-Ext application, that is using plain text passwords in its MySql database.
My plan was to use md5 hashes, as the existing passwords can be easily altered with the MySql function and I was expecting to find an easy solution for the GWT-Ext side as well. But as I found out, java.security is not supported by GWT and there doesn't seem to be any other implementation that can be used to change the password string to a md5 hash on client side.
Only "solution" I found so far, is to re implement a md5 method via JSNI as described here:
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/ad09475a9944c9f8
There is an existing user extension for Ext-JS, but I couldn't find anything for GWT-Ext:
http://extjs.com/forum/showthread.php?p=133516
Does anybody know a more elegant/simple way to solve this problem? Maybe I should use something else instead of md5 to make sure the passwords are encrypted?
Cheers
Frank
Personally, I would say you're doing it wrong. I wouldn't hash a password on the client side (which is what GWT is). If you hash your password, you will undoubtedly want to salt it, otherwise you will be susceptible to rainbow attacks. If you hash + salt it on the client side, your salt will be accessible to your users.
If I were you, I would hash + salt your password on the server side. This will allow you to use your standard Java code to perform your MD5 hash.
My 2 cents.
-JP
Another idea that may fit your need is something called zero knowledge auth. (Ie. the server never needs to know the user's plain text password.)
Basically, when setting the initial password, the client hashes the user's password N times (where N is a largish number like 1000), and then sends that final hash to the server along with N. The server stores the hash and N.
Later, when the user wants to authenticate, the server tells the client N-1, and the client hashes the password the user types N-1 times and sends that to the server. The server does 1 more hash on the received hash, and (hopefully) gets the stored hash. The server then stores the N-1 hash and N-1 number.
Each time the user authenticates, the server decrements the stored N and saves the previous hash.
When N gets down to 0, the user must choose and set a new password.
The server must ensure that it never asks for the same iteration, otherwise it is vulnerable to a replay. You can't really enforce that condition from the client side because the client (especially a browser) can't reliably keep track of the last N.
You can use gwt-crypto to generate SHA-1 hashes on the client side using:
String getSHA1for(String text) {
SHA1Digest sd = new SHA1Digest();
byte[] bs = text.getBytes();
sd.update(bs, 0, bs.length);
byte[] result = new byte[20];
sd.doFinal(result, 0);
return byteArrayToHexString(result);
}
String byteArrayToHexString(final byte[] b) {
final StringBuffer sb = new StringBuffer(b.length * 2);
for (int i = 0, len = b.length; i < len; i++) {
int v = b[i] & 0xff;
if (v < 16) sb.append('0');
sb.append(Integer.toHexString(v));
}
return sb.toString();
}
You should never use an md5 or other hash functions for password encryption. See http://codahale.com/how-to-safely-store-a-password/
You want gwt-crypto. It includes lots of standard crypto stuff.
Related
I came to know about jBCrypt for hashing a password and storing in DB. But I didnt find any option to get back the actual value from the hashed value. Only BCrypt.checkpw(password, hashedPassword) is available which is returning boolean.http://www.mindrot.org/projects/jBCrypt/
How can I get the actual value out of hashed value.
If it is not possible in jBCrypt, is there any other way to encrypt and decrypt values in java? Thanks in advance...
Instead of using a hash function, you can use a symmetrical encryption algorithm, like offered by Spring Security, from their Crypto Module, more specifically their Encryptors class.
Here is a basic encryption/decryption example:
public static void main(String[] args) {
final String salt = UUID.randomUUID().toString().replace("-", "");
TextEncryptor textEncryptor = Encryptors.delux("my-super-secure-password-for-the-encryptor", salt);
final String passwordToBeEncrypted = "my-secure-password-to-be-encrypted";
final String encrypted = textEncryptor.encrypt(passwordToBeEncrypted);
textEncryptor.decrypt(encrypted);
System.out.println(passwordToBeEncrypted.equalsIgnoreCase(textEncryptor.decrypt(encrypted)));
}
Here, I am using the delux. As per their documentation:
Creates a text encryptor that uses "stronger" password-based
encryption.
Keep in mind that this is a very naive approach of encrypting and decrypting.
I would not recommend you copy paste this solution in your production code.
In order for this functionality to be production ready, you want the password provided to the Encryptors.delux() to be stored somewhere safe.
Also, you also want to use a different way of generating a salt for your password (potentially a salt for each new password encryption) and storing it for later where you want to decrypt your password.
Also, you might want to not keep the password in plain text (String), but keeping it as char[] or byte[], but this should give a start from where you can start.
There is also a different library that does the same, from Apache, Apache Commons Crypto, which does utilize the same algorithms as Spring Crypto.
Keep in mind, you are more safe in using a library instead of implementing yourself, since using package javax.crypto will require you to know what you are doing and not do more harm than needed.
Side note: You might bump into the situation that your jdk is limited to 128 bits. To benefit from the 256bits, make sure you add the Java Cryptography Extension
The definition of a hash function has resistance to preimages: given h(x), it should be impossible to recover x. A hash function being "reversible" is the exact opposite of that property. Therefore, you cannot reverse hash function hence it is not possible to get actual value from hashed value.You cannot get x from h(x),only thing you can do is for the coming new password y compute h(y) and see if it is equal to h(x).
Not just jBcrypt any secured hash function won't provide this functionality of recovery
But I didnt find any option to get back the actual value from the hashed value
Well - that's the primary purpose of the cryptographic hash functions.
is there any other way to encrypt and decrypt values in java? Thanks in advance...
There are a lot of examples to encrypt / decrypt values in Java, just search for it, even here on SO. You may as well have a look into my blog about encryption in Java - it's about basic low level crypto API.
I hope you don't mean to use encryption for user passwords - even remote possibity to make the passwords reversible would make your system potentially dangerous for leaks.
In my code I want to store passwords... but since it's an online program, I want to keep the passwords secret (duh). So I used "Password Here".hashCode(). Perfect. I got a crazy new code. Now how to I see if the password (in the password field (JTextField)) matches the password. I DON'T WANT THE HASHCODE-ED PASSWORD! I WANT THE REAL PASSWORD! (The opposite of hashCode())
if (PasswordField.getText().equals("HASH NUMBER HERE!")) {
login(username, password, address, port);
But here I put in the already hashCode()-ed number... And I want it to be able to get the password before I changed it to hashCode()
I want to read the hashCode()-ed password into a not hashCoded()-ed String. the How do I do that?
Thanks!
You cannot "undo" (or "decrypt") a hash code. Hash codes are not a form of encryption.
First of all, you should not use hashCode() for passwords. You should use a cryptographic hash function instead.
The whole point of a cryptographic hash function is that it's a one way algorithm - given some input, you can compute the hash, but it is (practically) impossible to compute the original input back when you have only the hash.
How this normally works, is like this:
In a database, you store a user's name and the hash of the user's password.
When the user logs in, you calculate the hash of the password that the user entered when logging in.
You compare that hash to the hash in the database. If they are equal, the user entered the correct password.
As you see, it is not necessary to "decrypt" the hash when you do it this way.
In practice, there are a lot more details to it to make it really secure. You should use a strong cryptographic hash function and a salt to make it more secure. Make sure you study this carefully before using it in any serious application that's going to be available on the web.
There is no opposite of hashCode. To check if an entered password is equal to the hashed (stored) version, just hash the entered password and check it against the known (stored) hash. For instance, using the hashCode method, you compare the int values of the passwords:
int storedHash = getStoredHash();
String password = passwordField.getText();
if ( storedHash != password.hashCode() ){
//wrong
}
And side note: you might consider using something more secure than hashCode (MD5, SHA, etc...).
I know how to generate an MD5 Hash for a single string,
But what if I want to generate it like this:
String hash1 = GenHash(username:realm:password);
where the username and realm is fixed, the password is read from a text file which contain many words, and I want each of the words convert into md5 hash...
How can I do this ?
The reason why Neil is so adamant about not using MD5 (and he's right, by the way) is that MD5 is vulnerable to attack. This means that passwords could be recovered if an attacker finds the hash output. Since hashing passwords is generally done so that the preimage (i.e. the password) won't be revealed if the hash is found, you are strongly (oh so strongly) advised against using MD5. (In fact, if you're in business and you use MD5 for passwords, have fun with the negligence lawsuit. [Not legal advice]) Neil recommends some good hash algorithms. (Details of why MD5 is vulnerable are far beyond the scope of this question.)
Okay. Your question is how you hash multiple things together.
In order to hash multiple things together, you generally just concatenate them or otherwise just hash them in order without calling "digest()". (The order does matter, by the way.) In your case, since you have a wrapper on the hashing function, you would merely concatenate the strings together before hashing them.
String username = "myName";
String realm = "Narnia";
String password = "secret";
String hash = GenHash(username + realm + password);
In everyone else's case, they are probably using the standard Java MessageDigest, so they would call digest multiple times... after converting their strings to byte arrays. (Note that you're going to want to specify an encoding when converting a String to a byte array to ensure it's always done the same way, otherwise your hash function may return different results on different machines.)
byte[] usernameBytes; //Set equal to perhaps UTF32 encoding of the string
byte[] realmBytes; //Set equal to perhaps UTF32 encoding of the string
byte[] passwordBytes; //Set equal to perhaps UTF32 encoding of the string
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(usernameBytes); //Updates digest with these bytes
md.update(realmBytes); //Updates digest with these bytes
md.update(passwordBytes); //Updates digest with these bytes
byte[] hashResult = md.digest(); //Outputs result
//Insert code to convert the byte array to an outputtable form (or perhaps you're writing to a binary file)
But remember: using Strings presents a security vulnerability!
Strings should never be used for passwords since the string values cannot be guaranteed to be deleted (since they reside on the heap and are therefore "deleted" by the garbage collector whenever it maybe gets around to it, and by "deleted" I mean deallocated, not deleted). An attacker obtaining access to a memory dump could read the password. (Admittedly you have other problems if an attacker gets a memory dump, but don't make it worse.)
It is preferred that a char[] is used for all passwords or other very-sensitive text values. You would therefore create a new char array of size (username.length() + realm.length() + password.length()) then iterate over each of your strings and add each character to the new array... which you would then hash... then you would wipe all sensitive text values that you are no longer using (by iterating over each array and setting each element equal to (char)0).
Again, you cannot manually delete or wipe a string, but you can manually wipe a char or char[].
Why is char[] preferred over String for passwords?
While you're at it, look up password or hash salting. It may be useful for what you're doing.
I try to use PasswordMatcher with DefaultPasswordService with DefaultHashService.
DefaultHashService hashService = new DefaultHashService();
hashService.setHashIterations(10000);
hashService.setHashAlgorithmName(Sha512Hash.ALGORITHM_NAME);
hashService.setGeneratePublicSalt(true);
DefaultPasswordService passwordService = new DefaultPasswordService();
passwordService.setHashService(hashService);
String encryptedPassword = passwordService.encryptPassword("password");
System.out.println("Result:"+encryptedPassword);
And here is the result which I must save to database in the column PASSWORD.
$shiro1$SHA-512$10000$T5nkQEA3qjMLPuB/x+WN4Q==$qWViYjBljsMwH7FSvhecKlxQqXY11lv8eS4guxD9t8D4HTeKclN/muyTnhzYZ+YvI1YkEg6L7T2kM3qykUG0XQ==
Everything is working. However my question is why are iterations number and algorithm name saved together with salt and password? This case we do inform the potential attacker, who dumps our database about such important properties.
Nowadays, we aim to protect user passwords even when an attacker knows all implementation secrets. This is known as "white-box encryption":
In such a context, a ‘white-box attacker’ has full access to the software implementation of a cryptographic algorithm: the binary is completely visible and alterable by the attacker; and the attacker has full control over the execution platform (CPU calls, memory registers, etc.). Hence, the implementation itself is the sole line of defence.
That being said, you can store the hash algorithm and iteration count together with the password, as you have to assume the attacker also has access to the code/binaries anyways (which is not unlikely if they have access to the database).
Storing the number of iterations together with the hash has an additional benefit: In the future you might want to change to a larger number of iterations, since processing power has increased. You can then easily upgrade your database by going through all the hashes with the old number of iterations, apply a number of additional iterations and store the new result in the database, upgraded to a more secure scheme.
Similarly, if you add the hash algorithm to the hash, you may easily change to other password schemes (bcrypt, ...) later and upgrade users gracefully on their next login.
It is so when you change the default algorithm of your password service, you can still check against hashes of previously generated passwords.
As for your concern about aiding the potential hacker, there is a simple way to circumvent this, add a private salt string to the hashing algorithm:
private static final String PRIVATE_SALT = "some_random_string_you_only_know";
...
hashService.setPrivateSalt(new SimpleByteSource(PRIVATE_SALT));
I am looking for a simple and FAST algorithm to encrypt/decrypt a string (length is about 128 bytes) with a password.
Any good algorithms?
ADDED: Custom algorithm is absolutely OK. Less memory it take - better it is (for my case). No extra classes - perfect.
AES Algorithm : Implementation
AES is a federal standard for
private-key or symmetric cryptography.
It supports combinations of key and
block sizes of 128, 192, and 256.
How about IDEA - International Data
Encryption Algorithm ?
IDEA is the name of the patented and
universally applicable block
encryption algorithm, which permits
the effective protection of
transmitted and stored data against
unauthorized access by third parties.
See for the implementation : How to implement IDEA?
AES or 3DES are pretty "standard" symmetrical key encryptions. Blowfish is another.
Check http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html for using AES with Java, for instance.
Side note: If this is intended for securing something like passwords, you should really use a one-way hashing method instead (like MD5 or similar). Unless you absolutely have to be able to decrypt the text, one-way hashing is much safer. When, for instance, storing passwords in a database you would hash the password (with something like MD5) and store it. Validating a login is then done by hashing the user input and comparing it with the hashed value stored in the database.
See Java Crypto! for Encryption and Decryption
There is the Tiny Encryption Algorithm ( http://en.wikipedia.org/wiki/XXTEA ).
It's pretty simple and fast (for an encryption algorithm) and there are Java implementations.
Here is a simple encryption/decryption method. It is pretty weak, so I present it for, say education purpose:
public static String encDec(String input, String password) {
byte[] in = input.getBytes();
byte[] key = password.getBytes();
byte[] result = new byte[in.length];
int k = 0;
for (int i = 0; i < in.length; i++) {
result[i] = (byte)(in[i] ^ key[k]);
k++;
if (k == key.length)
k=0;
}
return new String(result);
}
It simply xors the bytes of a phrase with the bytes of a password. The same method can be used to encrypt and decrypt. Not a big challenge for a crypto analyst, by the way, but an easy start if you just need to obfuscate some data.
To make it a slightly better: don't pass a password String but a byte array with random values. But you wanted a method with a password, that's why I've implemented it that way ;)