I have a Dovecot server with MySQL database for storing usernames and passwords. The passwords in the database are in SHA512-CRYPT scheme.
I am inserting the hashed passwords in the database using a script.
doveadm pw -s SHA512-CRYPT -p password -r 500000
I want to hash the passwords using a JAVA application. I found this questions and I tried to create the same resulting hash using same password firstpassword and salt FooBarBaz. For some reason the resulting hash I get is different, although I am using the same hashing algorithm, salt and password.
Here is my Java code:
byte[] password = "firstpassword".getBytes();
byte[] salt = "FooBarBaz".getBytes();
MessageDigest digest = MessageDigest.getInstance("SHA-512");
digest.reset();
digest.update(salt);
byte[] hashed = digest.digest(password);
String encodedHash = Base64.getEncoder().encodeToString(hashed);
System.out.printf("{SHA512-CRYPT}$6$%s$%s", "FooBarBaz",encodedHash);
This outputs the hash:
{SHA512-CRYPT}$6$FooBarBaz$5WPtOnXVI/a6f003WByGKIcsfa6x0ansxiyE8uEfJ0TE5pI+Rv9kcMLgdZboKg7ZSWQgWFg+pIqruvdg6aiP/g==
I also tried swapping the order of salt + password to make it:
digest.update(password);
byte[] hashed = digest.digest(salt);
this gives me:
{SHA512-CRYPT}$6$FooBarBaz$QWS8+W5EWhModF+uO2tcsd55tDxzdzGJ5FurIbEgwVCwKfT5UqwIvBNG1Oyws8bZEFdeGgyD0u6zS1KArvGf9Q==
Does anyone have any idea how can I accomplish the same hash results in Java if I use the same password and salt?
The hash I am looking for is:
{SHA512-CRYPT}$6$FooBarBaz$.T.G.7FRJqZ6N2FF7b3BEkr5j37CWhwgvPOOoccrr0bvkBbNMmLCxzqQqKJbNhnhC.583dTBLEuZcDuQe7NEe.
doveadm uses the Unix crypt family of functions to generate the hash and outputs the hash as a Base64 encoded string. The alphabet used for the encoding (by crypt) is [a-zA-Z0-9./] (as mentioned on the man page for the functions). However, the alphabet used by the java.util.Base64 class is [A-Za-z0-9+/] (compliant with RFC 4648, as mentioned on the JavaDoc page for the Base64 class). Therefore, even if the hashed values are the same, they will get encoded differently.
A reliable option is to use the Crypt class from Apache Commons Codec as Crypt.crypt("firstpassword", "$6$FooBarBaz") (The prefix $6$ is mandatory to instruct Crypt that the SHA512-CRYPT algorithm needs to be used). This will generate your expected hash value.
Related
I am trying to make a Java program that requires a password. The problem is that a Java class or JAR file can be converted back to source code, so people can see the password by converting the program back to source code. How can I fix this?
You can't.
Even if you encrypt the password, the code to decrypt the password will be available in, and so will not prevent someone decompiling your application.
You have some options:
Put your password in an environment variable (accessible with System.getProperty("variable.name"))
Store the password in a file (still not great, but better than sources)
Access the password from a server, however, you are still required to make the user enter their creds for the server, and now you're left with the same problem.
Make the user enter a password every time they run the application
Probably the best way is to protect the password is to use a one-way hash. I would recommend investigating the Secure Hash Algorithms (SHA). These are one-way hashes (aka cryptographic checksums) that generate, for all practical purposes, a unique hash for some given text or message. Store the hash in the JAR file and the use the same algorithm to hash the entered password. Compare that hash to the stored one for verification.
The down side to this is that it is not easy (or in some cases possible) to change the password.
The odds of generating identical hashes for different inputs is infinitesimal.
Here is one way it could be done using standard Java libraries.
MessageDigest md = MessageDigest.getInstance("SHA-256");
String password = "Password"; // password to be "stored"
byte[] bytes = password.getBytes();
md.update(bytes);
byte[] digest = md.digest();
// store the following string in the jar file
String storedDigest = toHex(digest);
// validation process
String enteredPassword = "Password";
md.update(enteredPassword.getBytes());
System.out.println(toHex(md.digest()).equals(storedDigest) ? "Passed"
: "Failed");
//Convert array of bytes to a long hex string
public static String toHex(byte[] digest) {
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(Integer.toHexString((b >> 4) & 0xF));
sb.append(Integer.toHexString(b & 0xF));
}
return sb.toString();
}
I'm trying to produce the same hashes found in the linux shadow file using the MessageDigest, given the password, salt value and hashing algorithm, although the results do not match with what I get from the function below.
Hash Algorithm = 6
Password = mandar
Salt Value = 5H0QpwprRiJQR19Y
Expected Output = $6$5H0QpwprRiJQR19Y$bXGOh7dIfOWpUb/Tuqr7yQVCqL3UkrJns9.7msfvMg4ZOPsFC5Tbt32PXAw9qRFEBs1254aLimFeNM8YsYOv.
Actual Output = ca0d04319f273d36f246975a4f9c71d0184c4ca7f3ba54bc0b3e0b4106f0eefca1e9a122a536fb17273b1077367bf68365c10fa8a2b18285a6825628f3614194
I have this function for generating the hash value
public String getSha512Hash(String password, String saltValue) throws NoSuchAlgorithmException{
String text = saltValue + password ;
MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
byte[] bytes = messageDigest.digest( text.getBytes() );
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; ++i) {
sb.append(Integer.toHexString((bytes[i] & 0xFF) | 0x100).substring(1,3));
}
return sb.toString();
}
I'm referring to this website.
The passwords in /etc/shadow are hashed using the crypt(3) system call (man crypt).
You can use the Apache Commons implementation which should mimic the same behavior.
The fundamental problem is that the site you are referring to uses Perl's crypt() which seems a direct call to libc crypt(). In the manual of crypt is not specified how the SHA-512 hash is actually computed, but I searched GitHub and found this ~400 LOC source file sha512-crypt.c.
I read throught it and can't tell if it refers to some standard or if it's the only program using that algorithm. Since the SHA-512 thing also seems a proprietary extension to the POSIX standard, it's absolutely not unlikely.
You could ask the maintainer or the mailing list and report your findings back, otherwise if you absolutely need that functionality, you could write a native extension (don't know if there are Java libraries already available).
i try to find the good way for the best technology/method for hidden password in a file, but without use external jar or library.
Actually i use one object that represent a list of user name and password. Convert my list in a xml (only in memory) and after that, i store in a file with AES.
Use only java 7, no external library.
Is a good/secure method?
If this operation is no good, is possible to create dynamically xml encrypted?
thanks
You can use a FileOutputStream wrapped in a CipherOutputStream.
It's not really secure to save passwords encrypted with AES because:
1) Where do you store the key? If you store it in the server, if an attacker violates the server and finds the key, he will have complete acces to the users information.
2) Do you really need to know the users' passwords? In many application, for security reasons, it's better to keep only the hash of the password. The username can be stored in plaintext and you can also add a salt to the password to enforce it. You can do that with some algorithms offered by Java7 platform. In this way, even if someone enters your server, he can't use users login informations without breaking the hash function.
Here's an example that worked for me:
public byte[] getHash(String password, byte[] salt, String algorithm) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digest = MessageDigest.getInstance(algorithm);//The String rapresents the alg you want to use: for example "SHA-1" or "SHA-256"
digest.reset();
digest.update(salt);
return digest.digest(password.getBytes("UTF-8"));
}
You can also look at this link for a more complete example: https://www.owasp.org/index.php/Hashing_Java
I'm trying to use a Google's OAuth 2.0 for Server to Server Applications and I ran into a roadblock.
It states:
"Sign the UTF-8 representation of the input using SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) with the private key obtained from the API console. The output will be a byte array."
So I got most of down using Java libraries but how do I use a String as a private key?
I guess you need a fixed size key. So you can get the String,
hash the String and the result is your key for RSA.
Maybe this also helps:
bytes[] values = myString.getBytes(); //get byte[] from String
Is there an easy way in Java to generate password hashes in same form as generated by "openssl passwd -1".
Example:
# openssl passwd -1 test
$1$Gt24/BL6$E4ZsrluohHFxtcdqCH7jo.
I'm looking for a pure java solution that does not call openssl or any other external program.
Thanks
Raffael
The openssl docs describe the -1 option as: "Use the MD5 based BSD password algorithm 1."
Jasypt is a java cryptogrqphy library, as is jBCrypt. Jasypt is slightly more complicated, but more configurable.
I don't know that much about crypto, but my guess is that the password generated by openssl breaks down as:
$1$ - specifies that this was generated using the MD5 scheme
Gt24/BL6 - 8 byte salt
$ - delimiter
E4ZsrluohHFxtcdqCH7jo. - hash
so it looks like Jasypt's BasicPasswordEncryptor might be what you want-
Perhaps something like this?
MessageDigest md = null;
md = MessageDigest.getInstance("SHA");
md.update(pPassword.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = BASE64Encoder.encodeBuffer(raw);
The Java BASE64Encoder source can be found on the net.
You can find source code for the C language version here. It should be straightforward to convert it to pure Java.