I want to add some security to my project so I added a password field. In, order to store the password I was going to use a txt and save it in there, to add a bit more security I used the below code to hash the password(theirs more than one password saved this way if that's important). This is just and example of how I have done the hashing, the actual program uses text files etc.
public static void main(String[] args) throws NoSuchAlgorithmException {
System.out.println("Enter Password: ");
Scanner scanner = new Scanner(System.in);
String enteredPassword = scanner.nextLine();
String storedPassword = "�D�Ϛ-�UK�c�=�,�}��}��D��Zj>�m";
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(enteredPassword.getBytes());
String hashedString = new String(messageDigest.digest());
System.out.println(hashedString);
if(storedPassword.equals(hashedString)){
System.out.println("Passwords Match!");
}else{
System.out.println("Passwords Do Not Match!");
}
}
My question is am I doing this securely, besides decompiling my project and bypassing this feature is my project secure or can this method be exploited? Also, is there a way to secure a project against being decompiled and the code re-written to bypass security features?? Thank You
The approach itself is good; SHA-256 by itself is a strong, one-way hashing function. It cannot be "decrypted". But it's fast, thus allowing rapid brute-forcing of the password using a dictionary.
For better security you can slow things down with e.g. bcrypt or PBKDF2. Some 100ms will not be noticeable by the user, but makes brute-forcing impractical.
Here's an example with PBKDF2 using 100000 iterations of SHA-256. It also uses a random salt.
SecureRandom random = SecureRandom.getInstanceStrong();
byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("my-secret-password".toCharArray(), salt, 100000, 256);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = f.generateSecret(spec).getEncoded();
Base64.Encoder enc = Base64.getEncoder();
System.out.printf("salt: %s%n", enc.encodeToString(salt));
System.out.printf("hash: %s%n", enc.encodeToString(hash));
Note: PBKDF2WithHmacSHA256 is available since Java 8.
Here's a more complete example:
private static final SecureRandom random = new SecureRandom();
/**
* One-way encrypts (hashes) the given password.
*
* #param saltpw the salt (will be generated when null)
* #param pw the password to encrypt
* #return encrypted salted password
*/
public static String encrypt(String saltpw, String pw) throws GeneralSecurityException {
byte[] salt;
if (saltpw == null) {
salt = new byte[16];
random.nextBytes(salt);
} else {
salt = Base64.getDecoder().decode(saltpw.replaceFirst("\\$.*", ""));
}
KeySpec spec = new PBEKeySpec(pw.toCharArray(), salt, 100000, 256);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = f.generateSecret(spec).getEncoded();
Base64.Encoder enc = Base64.getEncoder();
return enc.encodeToString(salt) + "$" + enc.encodeToString(hash);
}
public static void main(String[] args) throws Exception {
String enc = encrypt(null, "my-secret-password");
System.out.printf("enc : %s\n", enc);
String test1 = encrypt(enc, "my-secret-password");
System.out.printf("test 1: %s, valid: %b\n", test1, enc.equals(test1));
String test2 = encrypt(enc, "some-other-password");
System.out.printf("test 2: %s, valid: %b\n", test2, enc.equals(test2));
}
Prints:
enc : B5V6SjkjJpeOxvMAkPf7EA==$NNDA7o+Dpd+M+H99WVxY0B8adqVWJHZ+HIjgPxMljwo=
test 1: B5V6SjkjJpeOxvMAkPf7EA==$NNDA7o+Dpd+M+H99WVxY0B8adqVWJHZ+HIjgPxMljwo=, valid: true
test 2: B5V6SjkjJpeOxvMAkPf7EA==$4H1SpH8N+/jqU40G6RWb+ReHUB3C58iAaU4l39j+TV8=, valid: false
Notice how test 1 results in exactly the same encrypted string as the original password, and that test 2 (with a wrong password) doesn't. So that's how you can verify that the provided password is valid or not, by just comparing the hashes.
There is no way to prohibit decompiling of java.
But you can make it hard to understand the decompiled code if you use an obfuscator.
E.g. https://www.guardsquare.com/en/products/proguard
This changes all you method-, class-, variable- names to meaningless short names.
A side-effect is that your class file will shrink too.
hey everyone am trying to find out which algorithm of hash is used my symfony FOS User Bundle I've done some research , and it's mentioned that FOSUser Bundle default security config uses Sha512() and itirate it over 5000 times + salt then bas64 encoding i'm actually new with these hash algorithms ,however this is the algorithm in php
$password = 'toto';
$salt = '1234';
$salted = $password.'{'.$salt.'}';
$digest = hash('sha512', $salted, true);
for ($i=1; $i<5000; $i++) {
$digest = hash('sha512', $digest.$salted, true);
}
$encodedPassword = base64_encode($digest);
}
taking from this post How do I generate a SALT in Java for Salted-Hash?
since am not familiar with java hash libraries can anyone help me how to translated this code into Java !
The solution is to use a Java API that encode the password like the MessageDigestPasswordEncoder:
Generate a salt (lenght=43):
private static String generateSalt() {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[SALT_SIZE];
random.nextBytes(salt);
String saltBase64_encoded=BaseEncoding.base64().encode(salt);
String saltPlusDot= saltBase64_encoded.replace("+",".");
return saltPlusDot.substring(0,saltPlusDot.length()-1);
}
BaseEncoding.base64() is a class in commons-codec api
concat: password + { + salt + }:
private static String mergePasswordAndSalt(String pass, String salt) {
if (salt == null) {
return salt;
}
String cg="{";String cd="}";
return pass+cg+salt+cd;
}
For each additional iteration: hash the concat of previous digest +
salt:
private static byte[] encodePassword(String password,String salt)
throws NoSuchAlgorithmException,UnsupportedEncodingException {
String mergedPasswordAndSalt =mergePasswordAndSalt(password, salt);
MessageDigest digester = MessageDigest.getInstance(ALGORITHM);
byte[] hash = digester.digest(mergedPasswordAndSalt .getBytes("UTF-8"));
for (int i = 1; i < ITERATIONS; ++i) {
hash = digester.digest(Bytes.concat(hash, mergedPasswordAndSalt.getBytes("UTF-8")));
}
return hash;
}
Bytes.concat(bytes ...) is a method in guava 19.0 api
This is the API in github FOSJcrypt
Symfony default setting for password encryption is Bcrypt this code mentioned in your security.yml config file
encoders:
Symfony\Component\Security\Core\User\User:
algorithm: bcrypt
cost: 15
in my case i used a trick since all my password start with 13 am assuming that the salt equals to 13
so i tried translating it into java by using the java BCrypt library
public boolean checkPassword(String passwordText, String DbHash) {
boolean password_verified = false;
if (null == DbHash || !DbHash.startsWith("$2a$")) {
throw new java.lang.IllegalArgumentException("Invalid hash provided for comparison");
}
password_verified = BCrypt.checkpw(passwordText, DbHash);
return (password_verified);
}
passwordText you actual password , DbHash stored hash
This code check a password hash if password match or not
there's a trick symfony hashed password start with $2y$ so to make this work you need to need change $2y$ to $2a$
for exemple i have password with a hash value that is stored in my database
String passwordText = "admin";
String DbHash = "$2y$13$VVmaKXzaS2QWgU1S4I8h5eJgC/DduF2fXmnhvcynro004GCUAQfr2";
change this :
String DbHash = "$2y$13$VVmaKXzaS2QWgU1S4I8h5eJgC/DduF2fXmnhvcynro004GCUAQfr2";
to this :
String DbHash = "$2a$13$VVmaKXzaS2QWgU1S4I8h5eJgC/DduF2fXmnhvcynro004GCUAQfr2";
I need a little help from you, I have an exercise , to do a login program and to store the password with sha-256 and salt, I made a part, but here it's the hard part. I've read that if you use sha-256 that you can't reverse the operation to determine the password. If it's true then what I need to use to encrypt the password and after I encrypt the password, how can I login if the password is encrypted?
PS: I've searched on google.
You should read about how hash functions work. Hash functions only produce a value, that depends on your input. Since the formula to calculate that value is always the same for a particular hash function (i.e. SHA-256), you can always produce it, if you know the input (the password in your case). So, unlike ciphers, a value calculated by the hash function is not supposed to be decrypted.
what I need to use to encrypt the password
You don't have to encrypt the password, since as you said, you cannot reverse the operation by just knowing the hash value, that's stored in you database. You can only gain access, if you know the password in plain text form.
Try the sample code below, it works well on my side
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Scanner;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.util.Base64.Decoder;
public class Cryptography {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {
Encoder encoder = Base64.getUrlEncoder().withoutPadding();
Decoder decoder = Base64.getUrlDecoder();
String integritystring = "810710202108241079100KAY435788318046";
String strSalt = "3a9IbkKNr2RjwFwGnPudHbLfA4zugj6TVcoBtlWpJl0m";
byte[] bSalt = Base64.getMimeDecoder().decode(strSalt);
System.out.println("Salt: " + strSalt);
System.out.println("integritystring: " + integritystring);
String strHash = encoder.encodeToString(Hash(integritystring, bSalt));
System.out.println("Hash: " + strHash);
}
private static byte[] Salt() {
SecureRandom random = new SecureRandom();
byte salt[] = new byte[6];
random.nextBytes(salt);
return salt;
}
private static byte[] Hash(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = factory.generateSecret(spec).getEncoded();
return hash;
}
}
Let's assume your password is 12345678. You are going to hash this password and save it to you program. In your login program you take the input from the user, hash it with the same algorithm and then compare the two hashed strings. If the are equal, the strings are equal, if not, they aren't equal. The person cannot figure out what the correct password is and you have hashed your password.
Let say i have encripted SHA1 password like this
String pass = "f6ce584e7b4ff5253eed4a2ea2b44247";
and i want make condition like this :
if (pass.equals("userinput")){
System.out.println("success");
}
please someone help me to make proper condition / function to compare those both value between user input and encripted password. Your help will be highly appreciated. thanks
SHA1 is a hash algorithm, which means that it is one-way. You can't get the original message after hashing it. Unlike encryption which is two-way (allows encryption and decryption).
This means that if you want to compare a hash, you don't try to get the original message. Instead, you hash the message-to-be-compared as well, then you perform the match:
So if the hashed pw is stored as:
String pass = "f6ce584e7b4ff5253eed4a2ea2b44247";
To match the subsequent input of the password, you do:
//check if hashed userInput is also "f6ce584e7b4ff5253eed4a2ea2b44247"
if(pass.equals(sha1(userInput))){
//do whatever
}
To implement a sha1() hash function, refer to: Java String to SHA1
To get your hashcode:
public static byte[] sha1(byte[] data)
Calculates the SHA-1 digest and returns the value as a byte[].
Parameters:
data - Data to digest
Returns:
SHA-1 digest
Found these at
https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/digest/DigestUtils.html#sha1Hex(java.lang.String)
This helps your process.
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jcajce.provider.asymmetric.rsa.DigestSignatureSpi.SHA1;
public class SHA1_test {
public static String sha1(String s, String keyString)
throws UnsupportedEncodingException, NoSuchAlgorithmException,
InvalidKeyException {
SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"),
"HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(key);
byte[] bytes = mac.doFinal(s.getBytes("UTF-8"));
return new String(Base64.encodeBase64(bytes));
}
public static void main(String[] args) throws InvalidKeyException,
UnsupportedEncodingException, NoSuchAlgorithmException {
Boolean validate = false;
String code = sha1("admin", "123456");
String your_user_inputString = "testpassword";
if (code.equals(sha1(your_user_inputString, "123456"))) {
System.out.println("Correct");
} else {
System.out.println("Bad password");
}
}
}
This works!!!
I need to hash passwords for storage in a database. How can I do this in Java?
I was hoping to take the plain text password, add a random salt, then store the salt and the hashed password in the database.
Then when a user wanted to log in, I could take their submitted password, add the random salt from their account information, hash it and see if it equates to the stored hash password with their account information.
You can actually use a facility built in to the Java runtime to do this. The SunJCE in Java 6 supports PBKDF2, which is a good algorithm to use for password hashing.
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 128);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = f.generateSecret(spec).getEncoded();
Base64.Encoder enc = Base64.getEncoder();
System.out.printf("salt: %s%n", enc.encodeToString(salt));
System.out.printf("hash: %s%n", enc.encodeToString(hash));
Here's a utility class that you can use for PBKDF2 password authentication:
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
/**
* Hash passwords for storage, and test passwords against password tokens.
*
* Instances of this class can be used concurrently by multiple threads.
*
* #author erickson
* #see StackOverflow
*/
public final class PasswordAuthentication
{
/**
* Each token produced by this class uses this identifier as a prefix.
*/
public static final String ID = "$31$";
/**
* The minimum recommended cost, used by default
*/
public static final int DEFAULT_COST = 16;
private static final String ALGORITHM = "PBKDF2WithHmacSHA1";
private static final int SIZE = 128;
private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})");
private final SecureRandom random;
private final int cost;
public PasswordAuthentication()
{
this(DEFAULT_COST);
}
/**
* Create a password manager with a specified cost
*
* #param cost the exponential computational cost of hashing a password, 0 to 30
*/
public PasswordAuthentication(int cost)
{
iterations(cost); /* Validate cost */
this.cost = cost;
this.random = new SecureRandom();
}
private static int iterations(int cost)
{
if ((cost < 0) || (cost > 30))
throw new IllegalArgumentException("cost: " + cost);
return 1 << cost;
}
/**
* Hash a password for storage.
*
* #return a secure authentication token to be stored for later authentication
*/
public String hash(char[] password)
{
byte[] salt = new byte[SIZE / 8];
random.nextBytes(salt);
byte[] dk = pbkdf2(password, salt, 1 << cost);
byte[] hash = new byte[salt.length + dk.length];
System.arraycopy(salt, 0, hash, 0, salt.length);
System.arraycopy(dk, 0, hash, salt.length, dk.length);
Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding();
return ID + cost + '$' + enc.encodeToString(hash);
}
/**
* Authenticate with a password and a stored password token.
*
* #return true if the password and token match
*/
public boolean authenticate(char[] password, String token)
{
Matcher m = layout.matcher(token);
if (!m.matches())
throw new IllegalArgumentException("Invalid token format");
int iterations = iterations(Integer.parseInt(m.group(1)));
byte[] hash = Base64.getUrlDecoder().decode(m.group(2));
byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8);
byte[] check = pbkdf2(password, salt, iterations);
int zero = 0;
for (int idx = 0; idx < check.length; ++idx)
zero |= hash[salt.length + idx] ^ check[idx];
return zero == 0;
}
private static byte[] pbkdf2(char[] password, byte[] salt, int iterations)
{
KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE);
try {
SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
return f.generateSecret(spec).getEncoded();
}
catch (NoSuchAlgorithmException ex) {
throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex);
}
catch (InvalidKeySpecException ex) {
throw new IllegalStateException("Invalid SecretKeyFactory", ex);
}
}
/**
* Hash a password in an immutable {#code String}.
*
* <p>Passwords should be stored in a {#code char[]} so that it can be filled
* with zeros after use instead of lingering on the heap and elsewhere.
*
* #deprecated Use {#link #hash(char[])} instead
*/
#Deprecated
public String hash(String password)
{
return hash(password.toCharArray());
}
/**
* Authenticate with a password in an immutable {#code String} and a stored
* password token.
*
* #deprecated Use {#link #authenticate(char[],String)} instead.
* #see #hash(String)
*/
#Deprecated
public boolean authenticate(String password, String token)
{
return authenticate(password.toCharArray(), token);
}
}
BCrypt is a very good library, and there is a Java port of it.
You could use Spring Security Crypto (has only 2 optional compile dependencies), which supports PBKDF2, BCrypt, SCrypt and Argon2 password encryption.
Argon2PasswordEncoder argon2PasswordEncoder = new Argon2PasswordEncoder();
String aCryptedPassword = argon2PasswordEncoder.encode("password");
boolean passwordIsValid = argon2PasswordEncoder.matches("password", aCryptedPassword);
SCryptPasswordEncoder sCryptPasswordEncoder = new SCryptPasswordEncoder();
String sCryptedPassword = sCryptPasswordEncoder.encode("password");
boolean passwordIsValid = sCryptPasswordEncoder.matches("password", sCryptedPassword);
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String bCryptedPassword = bCryptPasswordEncoder.encode("password");
boolean passwordIsValid = bCryptPasswordEncoder.matches("password", bCryptedPassword);
Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = new Pbkdf2PasswordEncoder();
String pbkdf2CryptedPassword = pbkdf2PasswordEncoder.encode("password");
boolean passwordIsValid = pbkdf2PasswordEncoder.matches("password", pbkdf2CryptedPassword);
You can comput hashes using MessageDigest, but this is wrong in terms of security. Hashes are not to be used for storing passwords, as they are easily breakable.
You should use another algorithm like bcrypt, PBKDF2 and scrypt to store you passwords. See here.
You can use the Shiro library's (formerly JSecurity) implementation of what is described by OWASP.
It also looks like the JASYPT library has a similar utility.
In addition to bcrypt and PBKDF2 mentioned in other answers, I would recommend looking at scrypt
MD5 and SHA-1 are not recommended as they are relatively fast thus using "rent per hour" distributed computing (e.g. EC2) or a modern high end GPU one can "crack" passwords using brute force / dictionary attacks in relatively low costs and reasonable time.
If you must use them, then at least iterate the algorithm a predefined significant amount of times (1000+).
See here for more: https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords
And here: http://codahale.com/how-to-safely-store-a-password/ (criticizes SHA family, MD5 etc for password hashing purposes)
And here: http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html (criticizes bcrypt and recommends scrypt and PBKDF2)
Fully agree with Erickson that PBKDF2 is the answer.
If you don't have that option, or only need to use a hash, Apache Commons DigestUtils is much easier than getting JCE code right:
https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/digest/DigestUtils.html
If you use a hash, go with sha256 or sha512. This page has good recommendations on password handling and hashing (note it doesn't recommend hashing for password handling):
http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
While the NIST recommendation PBKDF2 has already been mentioned, I'd like to point out that there was a public password hashing competition that ran from 2013 to 2015. In the end, Argon2 was chosen as the recommended password hashing function.
There is a fairly well adopted Java binding for the original (native C) library that you can use.
In the average use-case, I don't think it does matter from a security perspective if you choose PBKDF2 over Argon2 or vice-versa. If you have strong security requirements, I recommend considering Argon2 in your evaluation.
For further information on the security of password hashing functions see security.se.
As of 2020, the most reliable password hashing algorithm in use, most likely to optimise its strength given any hardware, is Argon2id or Argon2i but not its Spring implementation.
The PBKDF2 standard includes the the CPU-greedy/computationally-expensive feature of the block cipher BCRYPT algo, and add its stream cipher capability. PBKDF2 was overwhelmed by the memory exponentially-greedy SCRYPT then by the side-channel-attack-resistant Argon2
Argon2 provides the necessary calibration tool to find optimized strength parameters given a target hashing time and the hardware used.
Argon2i is specialized in memory greedy hashing
Argon2d is specialized in CPU greedy hashing
Argon2id use both methods.
Memory greedy hashing would help against GPU use for cracking.
Spring security/Bouncy Castle implementation is not optimized and relatively week given what attacker could use.
cf: Spring doc Argon2 and Scrypt
The currently implementation uses Bouncy castle which does not exploit
parallelism/optimizations that password crackers will, so there is an
unnecessary asymmetry between attacker and defender.
The most credible implementation in use for java is mkammerer's one,
a wrapper jar/library of the official native implementation written in C.
It is well written and simple to use.
The embedded version provides native builds for Linux, windows and OSX.
As an example, it is used by jpmorganchase in its tessera security project used to secure Quorum, its Ethereum cryptocurency implementation.
Here is an example:
final char[] password = "a4e9y2tr0ngAnd7on6P১M°RD".toCharArray();
byte[] salt = new byte[128];
new SecureRandom().nextBytes(salt);
final Argon2Advanced argon2 = Argon2Factory.createAdvanced(Argon2Factory.Argon2Types.ARGON2id);
byte[] hash = argon2.rawHash(10, 1048576, 4, password, salt);
(see tessera)
Declare the lib in your POM:
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm</artifactId>
<version>2.7</version>
</dependency>
or with gradle:
compile 'de.mkammerer:argon2-jvm:2.7'
Calibration may be performed using de.mkammerer.argon2.Argon2Helper#findIterations
SCRYPT and Pbkdf2 algorithm might also be calibrated by writing some simple benchmark, but current minimal safe iterations values, will require higher hashing times.
Here you have two links for MD5 hashing and other hash methods:
Javadoc API: https://docs.oracle.com/javase/1.5.0/docs/api/java/security/MessageDigest.html
Tutorial: http://www.twmacinta.com/myjava/fast_md5.php
Among all the standard hash schemes, LDAP ssha is the most secure one to use,
http://www.openldap.org/faq/data/cache/347.html
I would just follow the algorithms specified there and use MessageDigest to do the hash.
You need to store the salt in your database as you suggested.
i leaned that from a video on udemy and edited to be stronger random password
}
private String pass() {
String passswet="1234567890zxcvbbnmasdfghjklop[iuytrtewq##$%^&*" ;
char icon1;
char[] t=new char[20];
int rand1=(int)(Math.random()*6)+38;//to make a random within the range of special characters
icon1=passswet.charAt(rand1);//will produce char with a special character
int i=0;
while( i <11) {
int rand=(int)(Math.random()*passswet.length());
//notice (int) as the original value of Math>random() is double
t[i] =passswet.charAt(rand);
i++;
t[10]=icon1;
//to replace the specified item with icon1
}
return new String(t);
}
}
Here is my simple PasswordHasher class that I made:
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
public class PasswordHasher {
private static final String ALGO = "PBKDF2WithHmacSHA1";
private static final byte[] SALT = {
8, 8, 8, 8, 2,
8, 7, 7, 7, 2,
1, 1, 1, 1, 2,
11
};
private static final int ITERATION_COUNT = 1000;
private static final int KEY_LENGTH = 128;
private SecretKeyFactory mFactory;
byte[] hashPassword(String password) {
SecretKeyFactory factory = getFactory();
if (factory != null) {
try {
KeySpec spec = new PBEKeySpec(password.toCharArray(), SALT, ITERATION_COUNT, KEY_LENGTH);
return factory.generateSecret(spec).getEncoded();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
}
return null;
}
boolean verifyPassword(String password, byte[] expectedHashResult) {
byte[] hashedPassword = hashPassword(password);
if (hashedPassword == null) {
// Log fail result
return false;
}
return Arrays.equals(hashedPassword, expectedHashResult);
}
private SecretKeyFactory getFactory() {
if (mFactory == null) {
try {
mFactory = SecretKeyFactory.getInstance(ALGO);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
return mFactory;
}
}
import java.security.MessageDigest;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Base64;
import java.util.Properties;
public class Main{
public static void main(String[]a]{
//enter code here
}
public static String hashPassword(String password) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] hash = md.digest(password.getBytes());
return Base64.getEncoder().encodeToString(hash);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
hashPassword is the method that returns a hashed value when we pass a String as its parameter.
MessageDigest is the class that provides the interface for hashing password
getInstance is used to get the instance of a hashing algorithm such as MD-5,SHA 216,SHA-512 and so on.
The hashed Sting is in the forn of -byte []
In the return statement we convert the byte using ToString.