How to generate an MD5 Hash in this way? - java

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.

Related

jBCrypt Encrypt and Decrypt

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.

Comparing input password to stored hashed password in a web app

After reading this beautiful question: Why is char[] preferred over String for passwords?, I'm curious as to how this applies to servlet based web applications. Say your UI has some input field for the password, the password will be retrievable with request.getParameter("passwordFieldName") which returns a String. Even if you then convert it to a char[], you have to wait for GC to clear the String object.
Also, many of the Encryption/Hashing libraries I'm looking into using for password hashing have a method such as checkPassword(plaintext, hashed) that takes two Strings and returns true if the entered plain text string gives a hash equal to hashed. With this, even if you had a char[], you would still need to convert the array to a String with the new String(char[]) constructor.
It seems to me like you can't really avoid having your password as a String for comparing it to its stored representation. If you are worried about attacks during that small window, how do you protect yourself?
This is an overreaction and really just "security theater". There is really no scenario in which having a long String as a password in a Java application would be at all desirable to an attacker. If a memory exhaustion attack is a concern, then don't use Strings anywhere.
That being said CWE-521 states that passwords must have a max size. Strings don't really have a max size, and using a char[x] is a good way of enforcing a max size.

How to turn a MD5 Hash to a String?

I want to turn an MD5 Hash to a string:
public String MD5ToString(String plain) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();
md.update(plain.getBytes());
byte[] digest = md.digest();
BigInteger bigInt = new BigInteger(1,digest);
String hashtext = bigInt.toString(16);
// Now we need to zero pad it if you actually want the full 32 chars.
while(hashtext.length() < 32 ){
hashtext = "0"+hashtext;
}
return plain;
} catch (Exception e) {
System.out.println("Cannot encrypt String to Hash");
e.printStackTrace();
}
return null;
}
However i just get the Md5 back? Whats ms mistake?
UPDATE:
I changed the return type to hashtext, BUT when I want to convert a hash to a string I just get another has back:
String: test
Hash: 098f6bcd4621d373cade4e832627b4f6
String: fb469d7ef430b0baf0cab6c436e70375
I didn't analyze the code carefully but you return the object plain which has not changed. You should return hashText object if you want to get MD5 string returned from the method.
To have a usable string that you can send or store easily, the usual solution is to encode it in base64 (it's about 33% shorter than in hexa).
Here's one of the numerous tutorials you can find with Google : http://www.javatips.net/blog/2011/08/how-to-encode-and-decode-in-base64-using-java
In your precise case, as you seem to want the hexa representation, maybe you simply want to change
return plain;
to
return hashtext;
I changed the return type to hashtext, BUT when I want to convert a hash to a string I just get another hash back.
You seem to be under a misapprehension of what hashes are.
In general, hashing is a non-reversible transformation. You turn the hash back into a copy of the original string / object / whatever ... because much / most of the information content of the original has been thrown away. Indeed, there are an infinite number of possible input strings that hash to a given hash value, and there is no way of knowing which one is the right one. (They are all right.)
In the case of cryptographic hash functions like MD5, it is even worse. These functions are specifically designed to be non-reversible. Or more precisely, they are designed such that for a given the hash, the problem of recovering a possible input is computationally intractable.
Now it so happens that MD5 is weak ... and that if you have a large (but technically feasible) amount computational resources and time it is possible to reverse the hash. However, that doesn't address the first bullet point.
The bottom line is that if you want to be able to recover the original string you need to encrypt it rather than hash it.

Can I safely store a totally random string (any 16-bit value) into a SQLiteDB?

I've got a string which I created with a custom cipher, which can have any char value (0 through 0xFFFF). This string is created by taking an input plaintext and rotating each character by a pseudorandom value, so I have no control over what the output characters might be.
Can I safely store and retrieve this exactly without any issues into a SQLiteDatabase TEXT field?
I'm think that Java uses UTF-16, so I'm somewhat afraid of chars like NULL, END OF TEXT, ESCAPE, ', ", 0xfeff / 0xfffe (BOM) etc appearing in random places into my string, and I'm not really sure how SQLite will store this internally. If it uses any text-based markers to determine the start and end of fields I'm afraid this will fail.
Ideally I'd like to get back out the exact same character sequence I put in, so that I can put it through the reverse cipher.
I will be using the managed insert(ContentValues) method of SqLiteDatabase, so I think that this would take care of any issues regarding escaping the input string, but I'm still not quite convinced that this can work.
Is this a safe operation, and if not, what else should I do instead to store my encrypted string?
Avoid a Cryptographically weak custom cypher that also causes you problems, instead use Java's built in capabilities which can provide you with a cryptographically strong string.
http://docs.oracle.com/javase/1.4.2/docs/guide/security/jce/JCERefGuide.html#CipherClass
It would be safest to store it as a "blob" -- pretty much identical to a string, only with a separately-specified length.
C strings are generally assumed to be null-terminated.
In SQLite, strings must not contain end-of-string markser, i.e, characters with value zero.
However, you can store binary data as a blob.
This would look something like this:
SQLiteDatabase db = ...;
byte[] binaryData = ...;
ContentValues values = new ContentValues();
values.put("mycolumn", binaryData);
db.insert("mytable", null, values);
Cursor cursor = db.query("mytable", new String[]{"mycolumn"}, ...);
byte[] data = cursor.getBlob(0);
A simple and safe way to put String into the database that you are not sure if it will always work that I can think on top of my mind is to get the byte array:
void put(String key, byte[] value)
byte[] getAsByteArray(String key)
You can convert it to base64 string if you really need to store it as String (but why?) and get it back decoded.
That being said, you shouldn't need to do any of those because for the insert function, it should do the escaping for you if you use ContentValues.
ContentValue uses Parcel to do type changes

How to decrypt a SHA-256 encrypted string?

I have a string that was salted, hashed with SHA-256, then base64 encoded. Is there a way to decode this string back to its original value?
SHA-256 is a cryptographic (one-way) hash function, so there is no direct way to decode it. The entire purpose of a cryptographic hash function is that you can't undo it.
One thing you can do is a brute-force strategy, where you guess what was hashed, then hash it with the same function and see if it matches. Unless the hashed data is very easy to guess, it could take a long time though.
You may find the question "Difference between hashing a password and encrypting it" interesting.
It should be noted - Sha256 does not encrypt the data/content of your string, it instead generates a fixed size hash, using your input string as a seed.
This being the case - I could feed in the content of an encyclopedia, which would be easilly 100 mb in size of text, but the resulting string would still be 256 bits in size.
Its impossible for you to reverse the hash, to get that 100mb of data back out of the fixed size hash, the best you can do, is try to guess / compute the seed data, hash, and then see if the hash matches the hash your trying to break.
If you could reverse the hash, you would have the greatest form of compression to date.
SHA* is a hash function. It creates a representation (hash) of the original data. This hash is never intended to be used to recreate the original data. Thus it's not encryption. Rather the same hash function can be used at 2 different locations on the same original data to see if the same hash is produced. This method is commonly used for password verification.
You've done the correct thing by using a salt aka SSHA.
SHA and SHA-2 (or SHA-256) by itself without a salt are NOT considered secure anymore! Salting a SHA hash is called Salted SHA or SSHA.
Below is a simple example on how easily it is to de-hash SHA-1. The same can be done for SHA-2 without much effort as well.
Enter a password into this URL:
http://www.xorbin.com/tools/sha1-hash-calculator
Copy paste the hash into this URL:
https://hashes.com/en/decrypt/hash
Here's a page which de-hashes SHA-2. The way this pages works is somebody must have hashed your password before, otherwise it won't find it:
md5hashing dot net/hashing/sha256
Here's a page that claims to have complete SHA-2 tables available for download for a "donation" (I haven't tried it yet):
crackstation dot net/buy-crackstation-wordlist-password-cracking-dictionary.htm
Here's a good article that explains why you have to use SSHA over SHA:
crackstation dot net/hashing-security.htm

Categories

Resources