I am trying to generate signature token for distributed environment with java bcrypt algorithm,I want my token to be salted by some random string, just wanted suggestion about what can be the best way to create salt in this case so that I can retrieve my original string easily in other end.I started my implementation with sessionid, but sessionid wont be strong salt
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.
This question already has answers here:
Is it possible to decrypt MD5 hashes?
(24 answers)
Closed 5 years ago.
I am new in java and spring .I used Md5PasswordEncoder for password encoding.how can i decode it.
My encoding code is
Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
String monthlycost = md5PasswordEncoder.encodePassword(
empDetails.getMonthlyCost(), null);
String monthlyGrossSalary = md5PasswordEncoder.encodePassword(
empDetails.getMonthlyGrossSalary(), null);
please help me for decoding it
It seems, that you are not new to Java, but to programming in general. MD5 is a hashing algorithm. A hashing algorithm is (or should be) a one-way algorithm.
Example:
If you want to create a Login system or so you can save the password as md5, when a user registrates. When he tries to login, you can create the hash value and compare it with the one you saved, when he registrated. That assumes, that you don't have the password itself in your database.
You can read more about that here.
The whole point of a hashing algorithm such as MD5 is that you cannot decode it. It is a one-way function not an encryption algorithm.
So ... basically ... you can't decode it.
The way that this class is supposed to be used is that you start with the user's password in the clear when you are registering it. Then you hash the password (with a salt) and store the hash in the database. Later on, when the user tries to login, he/she presents the password in the clear again. You hash it (with the same salt) and then compare the hash with the hash that you stored previously. If the hashes are the same, then the user has supplied the correct password.
In other words, this gives you to check a user's password without storing the user's actual password (in the clear or encrypted) in your database.
In your code, you are trying to use the encoder for a purpose that it wasn't designed for. It is simply not applicable. Neither is Md5.
Here's a Q&A with an example of how to do encryption and decryption in Java:
https://stackoverflow.com/a/22445878/139985
I'm sure that you can find other examples using alternative libraries if you want to search.
You cannot!
From Javadoc of Md5PasswordEncoder:
As MD5 is a one-way hash, the salt can contain any characters
It is one-way hash, so you cannot decode it.
Would it make sense to encrypt the RSA keys of an encryption program I am writing with the java random number generator and a password as a seed? How secure would that make them?
It may make your RSA keys safer than you could expect. If the random number generator ever changes or if the password is only added as a seed then you lose the encrypted data.
You can always encrypt private keys with a password, but you should be using a known password based key derivation function (PBKDF) such as PBKDF2. PBKDF2 is specified in RFC 2898: PKCS #5: Password-Based Cryptography Specification v2.0.
So yes, encrypting a private key can provide a layer of protection. It should however not be performed with a random number generator. A well known protocol that encrypts the private key using a password is PGP. Password encryption can also be performed for the PKCS#12 container format (which actually refers back to PKCS#5).
How security it is depends on the system. A weak password will certainly hurt security though.
Is there a way to convert a string into a key so I can have the same encryption key for encoding/decoding? I do not mean using SecretKey btw.
Key symKey = KeyGenerator.getInstance(algorithm).generateKey();
I am using the DES algorithm btw
You probably mean a key derivation from a password. A popular approach is to use PBKDF2 in Java as discussed for example here. Don't forget to set the iteration count high to complicate brute-force attacks and set a random salt to prevent dictionary attacks.
A random salt is mandatory by now during user authentication, but it may also be used during encryption. It is just another public value that is added to the ciphertext like the IV for CBC mode.
Other alternatives would be bcrypt and scrypt which require additional libraries in Java.
Short question: I do NOT want to use bcrypt random generated salts. Let's say the password I am hashing is "abcd1234". In the good old days, the salt would be "ab" or "abcd" or "abcd12", in other words, the salt would be the first N characters of the password where N is the required minimum length of a password. So how do I generate a valid bcrypt salt from the password itself?
Long question: I am working with a messaging system, in other words, a message will be sent out internally for authentication and I cannot include the plain-text password in this message for obvious reasons. So the flow should be something like that:
Machine A gets the password in clear-text
Machine A hashes the password with bcrypt
The hashed (i.e. safe) password is sent in my internal message
Machine B, which is the authentication machine with the database of hashed passwords, get the message and now it has to compare the hashed password it received with the hashed password in the database for authentication.
But how can I do that if BCrypt does NOT allow me to use a salt derived from my plain-text password? Machine A knows nothing about any salt. It does not have any access to the database. Machine B is the one who will know that. So there must be a way to derive my bcrypt salt from "abcd1234" or bcrypt should have a method:
check(String hashedPasswordWithSaltA, String hashedPasswordWithSaltB);
Putting it down in straightforward terms: Machine A gets the password and Machine B is the one that has the authentication database. I don't want to have to pass the password in clear text from A to B, but it looks like bcrypt forces me to do that. :(
Just transmit the salt with the hashed password. The point of salting a password is so that in a database, two passwords that are the same in plaintext have different hashes. If you generate this salt from the password itself, this logic falls over. Additionally, as for decrypting purposes you have to store the salt in plaintext, you are essentially revealing a chunk of the users password.
TLDR: Let Bcrypt generate salts for you. Then transmit the salts with the hashed password. Salts are not meant to be secret.
You have actually two options to solve this problem.
1) Every website has this problem, because the password must be sent to the server. This is usually solved by using an encrypted connection (HTTPS/SSL). The password will only be encrypted (two-way), transferred to machine2 (server), decrypted and afterwards hashed.
2) You can hash the password on machine1 with BCrypt with a random salt, send it to machine2 and store the hash. To validate the password, machine1 would first have to ask machine2 for the used salt, then it hashes the password with this salt, and afterwards sends the hash to machine2. Machine2 can verify the password because the same salt was used.
I had a quick look at a jBCrypt example, it seems that you can generate the salt yourself and pass it as parameter. So you could actually derrive the salt from the password, but this makes the salt useless, it becomes just a more complex hash function.