I have built a function to hash the users password when they register using my java application. I am not sure how I should go about trying to verify their login since the password stored is going to be hashed.
I have tried making a function, that takes the entered password and hashes it and then compares the hash to the one in the database but, this didn't work since each time the hashing function is run on a password (String) the result is never the same. I am not sure how to verify the users password on login. Below I have provided:
Login button code
Generating secure password using salt function
Verification function
Login button code:
try {
// Get password from database and verify login
String slt = passwordUtils.getSalt(100);
Connection con = connectDB.getConnectionUser();
Statement stmt = null;
String sql = "SELECT * FROM USER where userEmail=?";
PreparedStatement pst = con.prepareStatement(sql);
pst.setString(1, userEmail.getText());
ResultSet rs = pst.executeQuery();
String fromDatabase = rs.getString(3); //get the password stored in database (hashed version)
String enteredPassword = String.valueOf(userPassword.getPassword()); //get entered password
if(rs.next()){
if(passwordUtils.verifyUserPassword(enteredPassword, fromDatabase, slt)){
JOptionPane.showMessageDialog(null, "Login details are correct. Welcome!");
con.close();
} else {
JOptionPane.showMessageDialog(null, "Invalid Log in details, try again.");
con.close();
}
}
} catch (SQLException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
Generate secure password function
public static String generateSecurePassword(String password, String salt){
String returnValue = null;
System.out.println("password supplied is: " + password + "salt added: " + salt);
System.out.println("");
byte[] securePassword = hash(password.toCharArray(), salt.getBytes());
System.out.println("");
System.out.println("secure pwd byte[]: " + securePassword);
System.out.println("");
returnValue = Base64.getEncoder().encodeToString(securePassword);
System.out.println("");
System.out.println("secure pwd converted " + returnValue);
return returnValue;
}
Verify login function
public static boolean verifyUserPassword(String providedPassword, String securedPassword, String salt){
boolean returnValue = false;
// generate new secure password with same salt
String newSecurePassword = generateSecurePassword(providedPassword, salt); //generate secure password using salt
//check to see if both passwords are the same
returnValue = newSecurePassword.equalsIgnoreCase(securedPassword);
System.out.println("Hashed password: " + securedPassword);
System.out.println("Verify hash: "+ newSecurePassword);
return returnValue;
}
Salting function
public static String getSalt(int length){;
StringBuilder returnValue = new StringBuilder(length);
for(int i = 0; i < length; i++){
returnValue.append(ALPHABET.charAt(RANDOM.nextInt(ALPHABET.length())));
}
System.out.println("final salt generated: " + returnValue);
return new String(returnValue);
}
Hashing function:
public static byte[] hash(char[] password, byte[] salt){
PBEKeySpec spec = new PBEKeySpec(password, salt, ITERATIONS, KEY_LENGTH);
Arrays.fill(password, Character.MIN_VALUE);
try{
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
System.out.println("skf return to secure password call: " + skf.generateSecret(spec).getEncoded());
return skf.generateSecret(spec).getEncoded();
} catch (NoSuchAlgorithmException | InvalidKeySpecException e){
throw new AssertionError("Error while hashing a password: " + e.getMessage(), e);
} finally {
spec.clearPassword();
System.gc();
}
}
After reading taking on board the feedback received under this post. I managed to solve the issue.
I created another column in the database which was storing Users and named the column "saltPassword". This would store the salt used on the password, which can later be retrieved to check password validation.
After storing the hashed password and the salt used in the database when a user registers. It became quite simple to perform password verification.
public boolean verifyPassword(String providedPassword, String fromdatabase, String passwordSalt){
boolean isValid = false;
String generate = passwordUtils.generateSecurePassword(providedPassword, passwordSalt);
isValid = generate.equals(fromdatabase);
return isValid;
}
This function was used for password verification.
It takes the password entered by the user in the password field, the password currently stored in the database (hashed) and the salt used for the password.
It then generates a salted password using the entered password along with the same salt used for the original password in the database. This should produce the same hashed password in the database. We then check that this is the case by applying .equals(fromdatabase) and checking if it's the same as the one in the database. If this is true, then the password is correct and the user can be logged in.
Related
I working on a log in system in Java and I am using PostgreSQL. I have a registration form that saves the user information to the database. It also hashes the password before storing. I am now trying to verify the password that the user enters against the hashed password in the database.
try {
//connects to the database
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/cc", "pi", "server");
//prepares SELECT statement
PreparedStatement statement = conn.prepareStatement("SELECT username, user_pass FROM users WHERE username = '" + username +"';");
ResultSet result = statement.executeQuery();
String upass = new String(password.getPassword());
String user = "";
String pass = "";
while(result.next()){
user = result.getString("username");
pass = result.getString("user_pass");
}
if(username.equals(user) && BCrypt.checkpw(upass, pass)){
frame.dispose();
new CommunityCooks();
}
else{
JOptionPane.showMessageDialog(null, "incorrect credentials");
}
}
catch(SQLException f){
f.printStackTrace();
}
This is the section that I am trying to verify the password matches. The "password" variable is a JPasswordField and the "username" variable is a JTextField. The stored credentials are 'tester' for the username and password and I am able to verify them as local variables and fields. I think the issue I am having is with the translation of the JTextField and the JPasswordField. What I am looking for help on is getting the username and password that the user enters to verify against the stored credentials after the password is hashed from the registration form. The issue I am having is that I can run the application and the login frame opens. I enter the test credentials and it is not matching. I’m getting my incorrect credentials message. I am unclear about the syntax for comparing the stored username (not hashed) and the stored password (hashed) against the user input credentials in the JTextField and the JPasswordField. I thought what I had was correct but it appears to not be right. The testing I have done for it works to read the database and verify but it is not working when I implement it in my program. The only difference in the two is the use of the fields where the test did not use them. My test is below:
public class Main {
public static void main(String[] args) {
String firstName = "tester";
String lastName = "tester";
String email = "tester";
String username = "tester";
String password = "tester";
try {
//connects to the database
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/cc", "pi", "server");
//inserts values into table
PreparedStatement statement = conn.prepareStatement("insert into users values(?,?,?,?,?)");
statement.setString(1, firstName);
statement.setString(2, lastName);
statement.setString(3, email);
statement.setString(4, username);
statement.setString(5, BCrypt.hashpw(password, BCrypt.gensalt()));
PreparedStatement st = conn.prepareStatement("SELECT username, user_pass FROM users WHERE username = '" + username + "';");
ResultSet result = st.executeQuery();
String u = null;
String p = null;
while (result.next()) {
u = result.getString("username");
p = result.getString("user_pass");
}
System.out.println(u);
System.out.println(p);
System.out.println(BCrypt.checkpw(password, p));
} catch(SQLException f){
f.printStackTrace();
}
}
}
The test output works and shows the username and the hashed password and stating that it is "true" to being verified.
Any guidance will be greatly appreciated. This is my first time using a hash system.
I am playing around with a login/register system for a desktop application. I have a register form and sign in form and the credential information is saved to a PostgreSQL database. I started out without encrypting information and everything is working but I now want to encrypt the password to save to the database. I am using Jasypt and got the password to encrypt and save to the database:
public void actionPerformed(ActionEvent e){
if(e.getSource() == registerButton){
try{
//connects to the database
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/cc","pi","server");
//inserts values into table
PreparedStatement statement = conn.prepareStatement("insert into users values(?,?,?,?,?)");
statement.setString(1, firstName.getText());
statement.setString(2, lastName.getText());
statement.setString(3, email.getText());
statement.setString(4, username.getText());
//checks password to ensure confirmation matches
//encrypts password for storing in database
if(password.getText().equals(confPass.getText())){
StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor();
String encryptPass = passwordEncryptor.encryptPassword(password.toString());
statement.setString(5, encryptPass);
statement.executeUpdate();
JOptionPane.showMessageDialog(null, "Registered Successfully");
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
else{
JOptionPane.showMessageDialog(null, "Password did not match");
}
} catch(SQLException f){
f.printStackTrace();
}
}
This works well and my password is encrypted. I am stumped on where to begin with getting the password from the database to compare the encrypted password to the user input. My sign in form to compare passwords (prior to encrypting the password):
public void actionPerformed(ActionEvent e){
//verify users credentials and signs in
if(e.getSource() == login){
try{
//connects to the database
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/cc","pi","server");
//inserts values into table
PreparedStatement statement = conn.prepareStatement("SELECT username, user_pass FROM users WHERE username = ? and user_pass = ?");
statement.setString(1, username.getText());
statement.setString(2, password.getText());
ResultSet result = statement.executeQuery();
if (result.next()) {
frame.dispose();
new CommunityCooks();
}
else {
JOptionPane.showMessageDialog(null, "Username or Password did not match.");
}
}
catch(SQLException f){
f.printStackTrace();
}
}
I made a test app to compare encrypted passwords and have a general idea of how it works:
import org.jasypt.util.password.StrongPasswordEncryptor;
public class EncryptTest {
public static void main(String[] args) {
String userPass = "test";
StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor();
String encryptPass = passwordEncryptor.encryptPassword(userPass);
System.out.println(encryptPass);
if(passwordEncryptor.checkPassword("test", encryptPass)){
System.out.println("correct");
}
else{
System.out.println("wrong");
}
}
}
The part that I am stumped on is trying to get the encrypted password and compare it to the user input password to validate. I believe I need to encrypt the input password and then can use the passworEncryptor.checkPassword(); but I don't know exactly where to put that in the sign in code and how to implement it. Any help would be great.
Thank you.
The name of the Java library Jasypt is shortened for "Java Simplified Encryption" and so this library is trying to avoid that
users are making implementations of crypto-routines that become insecure because of implementation errors.
The validation of a user password is as simple as your test app - you do not need to implement an encryption part, just pass the
password the user typed in your login form and pass it to the validation part
In details: There are two parts - in part 1 the user registers with his userPassword and passes it to the encryptPassword method:
String userPassword = "myPassword";
String encryptedPassword = passwordEncryptor.encryptPassword(userPassword);
encryptedPassword example: rCAgedhPnGoDZ1PF7hgspDIhLnLAHo536PSCKUfpYu8Yv0JHEcIZ3ZVHIHojBn1D
This encrypted password get stored in the database and you have to keep in mind that you cannot restore the original password from this string!
In part 2 the user tries to login with his loginPassword and passes it to the checkPassword method. The program loads the encryptedPassword from the database and passes the loginPassword together with the encryptedPassword. The result (boolean) is checked and the next steps in your program depend on the result, "true" means that the loginPassword is correct and "false" means that the loginPassword is not correct.
String loginPassword = "myPassword";
if (passwordEncryptor.checkPassword(loginPassword, encryptedPassword)) {
// correct!
System.out.println("correct passsword");
} else {
// bad login!
System.out.println("password not correct");
}
For more information you can check the "Easy usage" webpage: http://www.jasypt.org/easy-usage.html
I'm creating a web application. I'm using netbeans 7.4 and MySQL 6.1 for my database. I want to change the user's password. The structure of the password that is saved in the database is in md5. So, I have to convert the user's input for current password into md5 first and check the database if there's any match. Right now, I have a form structure in my ChangePassword.jsp. In the form are three fields for the current, new and retype password. Then through a servlet, I am manipulating these pieces of information.
The connection to the database is fine and I can already manage to encrypt the current password into md5. But, when I added a while(rs.next()) loop in my program to loop for all the results of my query, it doesn't work. So it won't forward to the desired jsp. Any suggestions on how I can do this? Any help will be much appreciated. Thanks in advance. This is my code.
try{
ServletContext context = getServletContext();
String currentPassword = request.getParameter("currentPassword");
String newPassword = request.getParameter("newPassword");
String tryNewPassword = request.getParameter("retypePassword");
String pswrd = "";
//For Password Encryption into md5
String md5 = null;
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(currentPassword.getBytes(), 0, currentPassword.length());
md5 = new BigInteger(1, digest.digest()).toString(16);
//Database Connection
Class.forName(context.getAttribute("dbdriver").toString());
String db = context.getAttribute("connstr").toString();
Connection conn = DriverManager.getConnection(db);
Statement stmt = conn.createStatement();
stmt = conn.createStatement();
//Check Database Connection
if (conn != null) {
JOptionPane.showMessageDialog(null, "Connected!");
} else {
JOptionPane.showMessageDialog(null, "Not Connected!");
}
String query = "SELECT password FROM accounts WHERE password='"+md5+"'";
ResultSet rs = stmt.executeQuery(query);
JOptionPane.showMessageDialog(null, "Entering while loop");
while(rs.next()){
if(md5CurrentPasswrd.equals(rs.getString(1))){
if(newPassword == tryNewPassword){
digest.update(newPassword.getBytes(), 0, newPassword.length());
md5NewPasswrd = new BigInteger(1, digest.digest()).toString(16);
String queryUpdate = "UPDATE accounts SET password='"+md5NewPasswrd+"' /n"
+ " WHERE password='"+md5CurrentPasswrd+"'";
PreparedStatement prepStmt = conn.prepareStatement(queryUpdate);
prepStmt.executeUpdate();
response.sendRedirect("/Project1/PasswordSaved.jsp");
}else{
response.sendRedirect("/Project1/PasswordNotSaved.jsp");
}
}else{
response.sendRedirect("/Project1/PasswordNotSaved.jsp");
}
pswrd = rs.getString(1);
JOptionPane.showMessageDialog(null, "Running while loop");
}
JOptionPane.showMessageDialog(null, "End of while loop");
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(ChangePassword.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(ChangePassword.class.getName()).log(Level.SEVERE, null, ex);
} catch (SQLException ex) {
Logger.getLogger(ChangePassword.class.getName()).log(Level.SEVERE, null, ex);
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
OK so I am trying to create user authentication for a little Java project of mine and I've run into a bit of a road block.
I have a table called user_info with 3 columns; id, user and password.
I realized that I should probably have some form of encryption, so I used Java's MessageDigest to encrypt the password with SHA1. Since I don't yet have a website for people to register (and have PHP enter the encrypted PW into the database), I simply encrypted a test password and replaced the unencrypted password in the database with the encrypted one.
For example, a user with username test and password test has an encrypted password of:
895df4f75b316de68d167ed2e83adb0bedbbde17
So my database has an entry with id 0, user test and password 895df4f75b316de68d167ed2e83adb0bedbbde17.
Now my Java code to check if the person provided valid details had no issue until I started using encrypted passwords.
Here is the login code for my Java application:
public int doLogin(String username, String pass) {
EncryptionHandler e = new EncryptionHandler();
String userToLogIn = username;
String userToLogInPassword = pass;
try {
String fixedUser = prepString(userToLogIn);
String fixedPass = e.doEncryptPassword(prepString(userToLogInPassword));
System.out.println(fixedPass);
con = DriverManager.getConnection(url, user, password);
st = con.createStatement();
rs = st.executeQuery("SELECT * FROM `user_info` WHERE `user` = " + fixedUser + " AND `password` = " + fixedPass);
if (rs.next()) {
//System.out.println("ID: " + rs.getString(1) + ", USER: " + rs.getString(2) + ", PASSWORD: " + rs.getString(3));
return 1;
} else {
System.out.println("Username or password is invalid!");
return 0;
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
} finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
}
}
return 0;
}
private String prepString(String s) {
return new StringBuilder().append("'").append(s).append("'").toString();
}
and in case it's needed, my encryption method:
public String doEncryptPassword(String s) {
MessageDigest sha1;
try {
sha1 = MessageDigest.getInstance("SHA1");
byte[] digest = sha1.digest((s).getBytes());
return bytes2String(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return s;
}
private static String bytes2String(byte[] bytes) {
StringBuilder string = new StringBuilder();
for (byte b : bytes) {
String hexString = Integer.toHexString(0x00FF & b);
string.append(hexString.length() == 1 ? "0" + hexString : hexString);
}
return string.toString();
}
Again, using unencrypted passwords works just fine, but as soon as I encrypt the password I get the unknown column error. In this example (user test, password test), passing the unencrypted password receives no error, but using the encrypted password 895df4f75b316de68d167ed2e83adb0bedbbde17 provides me the error:
Unknown column '895df4f75b316de68d167ed2e83adb0bedbbde17' in 'where clause'
Ignoring that this isn't encryption, you have invalid SQL because of quoting problems. As #Leigh notes in the comments, you put quotes at the beginning and end of your password string ... then hash it. Your quotes are now dearly departed.
Of course you should never create SQL like this in the first place. Use prepared statements -> Oracle Prepared Statements Tutorial
Get rid of any of your own home-grown string quoting then simply do:
String sqlString = "SELECT * FROM user_info WHERE user = ? AND password = ?";
PreparedStatement ps = con.prepareStatement(sqlString);
ps.setString(1, username);
ps.setString(2, hashedPassword);
ResultSet rs = ps.executeQuery();
You need to do your prepString thingy as well for the password:
String fixedPass = prepString(e.doEncryptPassword(userToLogInPassword));
But it isn't a good idea to build statements this way.
Use prepared statements.
Hello I am trying to create a login form in java netbeans IDE. My aim is to create multiple user ID's and their respective passwords. I have given textfields to userID and passwordField for passwords to get the values but the problem is i want to get the text from the password field and i am unable to get it its showing some error i think there is some problem with syntax my research is as follows can there be any solution? Need your help
private void lb_loginMouseClicked(java.awt.event.MouseEvent evt) {
DBUtil util = new DBUtil();
String value1=tb_uid.getText();
String value2=tb_pwd.getPassword();
String user1="";
String pass1="";
try {
Connection con = util.getConnection();
PreparedStatement stmt = con.prepareStatement("SELECT * FROM login where username='"+value1+"' && password='"+value2+"'");
ResultSet res = stmt.executeQuery();
res = stmt.executeQuery();
while (res.next()) {
user1 = res.getString("username");
pass1 = res.getString("password");
}
if (value1.equals(user1) && value2.equals(pass1)) {
JOptionPane.showMessageDialog(this,"correct");
}
else{
JOptionPane.showMessageDialog(this,"Incorrect login or password","Error",JOptionPane.ERROR_MESSAGE);
}
JOptionPane.showMessageDialog(null, "COMMITED SUCCESSFULLY!");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
}
String pwd = new String(jPasswordField1.getPassword());
Option 1:
jTextField1.setText(""+pwd);
Option 2:
System.out.println(""+pwd);
Use this code:
String password = String.valueOf(jPasswordField.getPassword());
The JPasswordField is encrypted but if you use String.valueOf it will converted Char to String.
value2 is char array so doing String concatenation would result in the String representation of the array rather then the String content itself ending up in the SQL. You could replace
PreparedStatement stmt = con.prepareStatement("SELECT * FROM login where username='"+value1+"' && password='"+value2+"'");
with
PreparedStatement stmt = con.prepareStatement("SELECT * FROM login where username='"+value1+"' AND password='" + new String(value2) + "'");
Similarly
if (value1.equals(user1) && value2.equals(pass1)) {
would need to be
if (value1.equals(user1) && pass1.equals(new String(value2)) {
Better use the PreparedStatement placeholders however, to protect against SQL injection attack:
PreparedStatement stmt = con.prepareStatement("SELECT * FROM login where username=? AND password=?);
stmt.setString(1, value1);
stmt.setString(2, new String(value2));
Note: This is not a secure way do to a password lookup, a hashed comparison would be relatively safer.
From http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#equals%28java.lang.Object%29:
equals
public boolean equals(Object anObject)
Compares this string to the specified object. The result is true if
and only if the argument is not null and is a String object that
represents the same sequence of characters as this object.
Your code:
char[] value2=tb_pwd.getPassword();
...
String pass1="";
...
...&& value2.equals(pass1)...
Seems like you'd want to convert your char array into String then retry the conversion. If you're still getting an error please post it along with relevant input so we can see what is being received.
You want to convert your char[] to a String. When you envoke tb_pwd.getPassword() a char[] (character array) is returned. If you want to compare this password you must convert it to a String, and for this you can use this method:
String final_pass = "";
for(char x : passwordAsChar[]) {
final_pass += x;
}
As for comparing passwords in databases you should never store them in plain-text, unencrypted. You could store an MD5 string in your database, and the convert your password inputted by the user to a String, and then envoke the following method on it. Then compare the returned String with the one from the database. If they match, the user has entered a correct password.
Example:
char[] pass = tb_pwd.getPassword();
String final_pass = "";
for (char x : pass) {
final_pass += x;
}
String md5_encrypted_pass_userInput = encrypt(final_pass);
if (md5_encrypted_pass.equals(pass1)) { /* pass1 = the password from the database */
// Correct password
}
A method to use for encrypting Strings to MD5 is:
public static final String encrypt(String md5) {
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] array = md.digest(md5.getBytes());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; ++i) {
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {}
return null;
}