2

I need to write a little program in Java that asks a person to enter a Pin Code. So I need the Pin to be hidden with asterisks (*) instead of the numbers. How can I do that?

So far, this is my code :

import java.util.Scanner;
import java.io.*;


public class codePin {

    public static void main(String[] args){

        int pinSize = 0;

        do{
            Scanner pin = new Scanner(System.in);
            System.out.println("Enter Pin: ");
            int str = pin.nextInt();
            String s = new Integer(str).toString();

            pinSize = s.length();

            if(pinSize != 4){
            System.out.println("Your pin must be 4 integers");
            } else {
            System.out.println("We're checking if Pin was right...");
            }

        }while(pinSize != 4);
    }
}

Actually this program works for now, but I want to add a functionality to display Pin like "* * * " or " * *" etc... (in the console when the Person enters is own Pin). I found something to entirely hide the Pin, but I do not want this. I want the Pin with asterisks

Any ideas ? Thanks

hacks4life
  • 691
  • 5
  • 16
  • 38
  • check these out http://stackoverflow.com/questions/12076165/how-to-obscure-scanner-input-text and http://stackoverflow.com/questions/10819469/hide-input-on-command-line – Serge Mar 20 '14 at 21:38
  • I already tried this one, but it hides it, it does not display asterisks – hacks4life Mar 20 '14 at 21:39
  • There is JLine, but it requires native libraries to work on Windows... – fge Mar 20 '14 at 21:51

2 Answers2

3

Something like this:

import java.io.*;

public class Test {
    public static void main(final String[] args) {
        String password = PasswordField.readPassword("Enter password:");
        System.out.println("Password entered was:" + password);
    }
}


class PasswordField {

   public static String readPassword (String prompt) {
      EraserThread et = new EraserThread(prompt);
      Thread mask = new Thread(et);
      mask.start();

      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      String password = "";

      try {
          password = in.readLine();
      } catch (IOException ioe) {
          ioe.printStackTrace();
      }
      et.stopMasking();
      return password;
   }
}   

class EraserThread implements Runnable {
   private boolean stop;

   public EraserThread(String prompt) {
       System.out.print(prompt);
   }

   public void run () {
      while (!stop){
         System.out.print("\010*");
         try {
            Thread.currentThread().sleep(1);
         } catch(InterruptedException ie) {
            ie.printStackTrace();
         }
      }
   }

   public void stopMasking() {
      this.stop = true;
   }
}
elias
  • 15,010
  • 4
  • 40
  • 65
  • 1
    Perfect ! It does work. I just have one question, when executing this code, it displays "Enter passwordµ", I do not know where does that first asterisk come from ? – hacks4life Mar 21 '14 at 08:17
  • BufferedReader(InputStreamReader(System.in)) is actually a better console reader compared to Console and Scanner http://stackoverflow.com/questions/4644415/java-how-to-get-input-from-system-console/4645193#4645193 Good password masking solution for using BufferedReader. – oraclesoon Mar 22 '17 at 11:11
  • @hacks4life this is basically a hack, "\010" is a backspace character, so this thread is eternally pressing backspace + *, resulting in constant printing of star and deleting it. Once u type anything that is one more character to delete and hence star is left. But because the very first backspace is useless the first star ends up staying printed. – J Asgarov Aug 21 '23 at 09:08
2

The Console class is the correct way to read passwords from the command line. However, it doesn't print asterisks, as that would leak information in general (not in the case where a PIN is known to be 4 digits). For something like that, you'd might need a curses library.

erickson
  • 265,237
  • 58
  • 395
  • 493