1

I'm making a basic user authentication system on console in java. The user enters their username and password and I store the encrypted password with SHA-512 in a file. Then I prompt the user to "log in" and i need to validate that the password they input this time is the password they entered when they "signed up". The problem arises in the validation part. When i store the password, I store the salt along with it in the file. But because the salt is a byte[] array, it shows the same [B@232204a1 when i convert it to a string and store it in the file.

Through this answer what i did was that i stored the salt byte array values in a string by concatenating them together so it'd be a continuous value and easier to read during validation.

In the validation part, i read the stored salt correctly, but when i use .getBytes() and then use the same code from the link above, it ouputs a different value than the one i had stored. And hence when i use it to calculate the hashed password, it obviously gives me the wrong answer.

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Scanner;

public class authenticationSystem {
     private byte[] salt;
    public static void main(String[] args) throws NoSuchAlgorithmException
    {
        Scanner sc = new Scanner(System.in);

        byte[] salt = getSalt();

        System.out.println("Enter 1 for Sign up and 2 for log in and -1 to exit");
        int option = Integer.parseInt(sc.nextLine());

        switch(option) {
            case 1:
                System.out.println("Enter Username: ");
                String username = sc.nextLine();

                System.out.println("Enter Password: ");
                String passwordToHash = sc.nextLine();

                boolean signupResult = signUp(username, passwordToHash, salt);

                if(signupResult == false) {
                    System.exit(0);
                }

                else {
                    System.out.println("SignUp Successful");
                    break;
                }
            case 2:

                System.out.println("Enter Username: ");
                username = sc.nextLine();

                System.out.println("Enter Password: ");
                passwordToHash = sc.nextLine();

                boolean loginResult = logIn(username, passwordToHash);

                if(loginResult == false) {
                    System.out.println("Authentication Failed!");
                    break;
                }

                else {
                    System.out.println("Authentication Successful!");
                    break;
                }

        }
}




   private static boolean logIn(String username, String password) {

       String absolutePath = "C:\\Users\\asadn\\eclipse-workspace\\output.txt";

       File file = new File(absolutePath);


       try(BufferedReader bufferedReader = new BufferedReader(new FileReader(absolutePath))) {  
        String currentLine = null;
        int count=1;
           while((currentLine = bufferedReader.readLine()) != null) {
               if(currentLine.equals(username)) {

                   currentLine = bufferedReader.readLine(); //get to line with salt
                   System.out.println(currentLine);
                   byte[] salt = currentLine.getBytes();
                   System.out.println(salt);

                   for(int i = 0; i<salt.length; i++) {
                        System.out.print(salt[i] & 0x00FF);
                        System.out.print("");
                    }
                   System.out.println("");
                   currentLine = bufferedReader.readLine(); //get to line with hashedPassword

                   String passwordToMatch = currentLine; //store in a string variable for comparison

                   System.out.println(passwordToMatch);

                   String passwordRetrieved = get_SHA_512_SecurePassword(password, salt);
                   System.out.println(passwordRetrieved);
                   if(passwordToMatch.equals(passwordRetrieved)){
                       return true;
                   }
               }
           }


       } catch (FileNotFoundException e) {
           // exception handling
       } catch (IOException e) {
           // exception handling
       }
       return false;
   } 

    private static boolean signUp(String username, String hashedPassword, byte[] salt) {

        String absolutePath = "C:\\Users\\asadn\\eclipse-workspace\\output.txt";

        File file = new File(absolutePath);

        String saltInStringFormat = "";

        for(int i = 0; i<salt.length; i++) {
            saltInStringFormat+=Integer.toString(salt[i] & 0x00FF);
        }
     // write the content in file 
        try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, true))) {  
            String securePassword = get_SHA_512_SecurePassword(hashedPassword, salt);
            bufferedWriter.write(username);
            bufferedWriter.newLine();
            bufferedWriter.write(saltInStringFormat);
            bufferedWriter.newLine();
            bufferedWriter.write(securePassword);
            bufferedWriter.newLine();
            bufferedWriter.close();
        } catch (IOException e) {
            // exception handling
            return false;
        }
        return true;
    }


    private static String get_SHA_512_SecurePassword(String passwordToHash, byte[] salt)
    {
        //Use MessageDigest md = MessageDigest.getInstance("SHA-512");
        String generatedPassword = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-512");
            md.update(salt);
            byte[] bytes = md.digest(passwordToHash.getBytes());
            StringBuilder sb = new StringBuilder();
            for(int i=0; i< bytes.length ;i++)
            {
                sb.append(Integer.toString((bytes[i] & 0xff + 0x100), 16).substring(1));
            }
            generatedPassword = sb.toString();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        return generatedPassword;
    }

    //Add salt
    private static byte[] getSalt() throws NoSuchAlgorithmException
    {
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        byte[] salt = new byte[16];
        sr.nextBytes(salt);
        return salt;
    }
}

Now I understand that I'm going wrong in the conversion of byte to string and back but I have no other idea of how to make this work with a file. I'd really appreciate it if someone could help me.

Asad Nawaz
  • 355
  • 1
  • 3
  • 14
  • Try writing `new String(bytes)` instead of `bytes.toString()` – Bohemian Dec 06 '18 at 23:07
  • @bohemian, where exactly? – Asad Nawaz Dec 06 '18 at 23:09
  • This will fail because the salt may contain a newline character which would disturb the file format. Most simple solution: Store the salt in hexadecimal representation. This doubles the needed storage but avoids a lot of problems. – Michael Butscher Dec 06 '18 at 23:11
  • @Michael Butscher the salt is in byte[] format, how can I change byte[] to hexadecimal? – Asad Nawaz Dec 06 '18 at 23:14
  • 2
    One direction: https://stackoverflow.com/questions/2817752/java-code-to-convert-byte-to-hexadecimal and back: https://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java – Michael Butscher Dec 06 '18 at 23:17
  • @Michael Butscher this was the hex form stored in the file `54 40 9C 55 04 F5 00 AB 53 1D 1B F3 AE EA E9 EB` and this is what was read back from it `84 244 255 156 245 79 4 255 79 0 250 175 83 241 207 27 255 47 174 254 159 233 254 175` it went from 16 bytes to 24 bytes – Asad Nawaz Dec 06 '18 at 23:28
  • If you used the best rated answers from my links you should be aware that the one conversion function places spaces between the hexadecimal byte representations while the opposite function doesn't expect spaces. You may have to adapt the function. – Michael Butscher Dec 06 '18 at 23:35
  • @Michael Butscher Yes, it worked! I realized that after i commented. Thank You! – Asad Nawaz Dec 06 '18 at 23:46

0 Answers0