52

How to mask a password from console input? I'm using Java 6.

I've tried using console.readPassword(), but it wouldn't work. A full example might help me actually.

Here's my code:

import java.io.BufferedReader;
import java.io.Console;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test 
{   
    public static void main(String[] args) 
    {   
        Console console = System.console();

        console.printf("Please enter your username: ");
        String username = console.readLine();
        console.printf(username + "\n");

        console.printf("Please enter your password: ");
        char[] passwordChars = console.readPassword();
        String passwordString = new String(passwordChars);

        console.printf(passwordString + "\n");
    }
}

I'm getting a NullPointerException...

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
New Start
  • 1,401
  • 5
  • 21
  • 29

5 Answers5

71

A full example ?. Run this code : (NB: This example is best run in the console and not from within an IDE, since the System.console() method might return null in that case.)

import java.io.Console;
public class Main {

    public void passwordExample() {        
        Console console = System.console();
        if (console == null) {
            System.out.println("Couldn't get Console instance");
            System.exit(0);
        }

        console.printf("Testing password%n");
        char[] passwordArray = console.readPassword("Enter your secret password: ");
        console.printf("Password entered was: %s%n", new String(passwordArray));

    }

    public static void main(String[] args) {
        new Main().passwordExample();
    }
}
Hugues M.
  • 19,846
  • 6
  • 37
  • 65
bilash.saha
  • 7,226
  • 2
  • 35
  • 40
  • I just got another NullPointerException... I don't understand! – New Start Nov 15 '11 at 15:16
  • 2
    Are you running this from within an IDE? Is not the code running ? Why downvote ? – bilash.saha Nov 15 '11 at 15:18
  • i didn't downvote, it must have been PTBG... I'm not sure why he did to be honest! – New Start Nov 15 '11 at 15:20
  • yeah, it's not getting the Console instance... is that because i'm inside Eclipse? – New Start Nov 15 '11 at 15:22
  • Its okey.This example is best run in the console and not from within an IDE, since the System.console() method might return null in that case.Run it in the console.It must work.Yes it may not work inside eclipse. – bilash.saha Nov 15 '11 at 15:22
  • 14
    For the guys getting the null pointer, run it from console, from eclipse this will not work – Sinisha Mihajlovski Dec 20 '12 at 15:36
  • This is also highly insecure. – Woot4Moo Apr 22 '14 at 20:55
  • 5
    @Woot4Moo Can you clarify why this is "highly insecure"? Without any context of why, the statement alone isn't very useful for promoting understanding (nor is it easy to verify or refute). – M. Justin Sep 18 '15 at 03:58
  • how to get password properly so that it will be running properly from console as well as the ide? – inquisitive Sep 21 '15 at 05:28
  • For those who want to run their solutions both from console and the IDE, my solution is to have a switch statement. If the program runs without arguments enters the "interactive" mode with the console object, otherwise uses the given ones. Then, in your IDE you should be able to explicit a default set of arguments to run the application. – Pablo Torrecilla Nov 03 '16 at 01:00
  • Here's an example: `final String passwd; final String message = "Enter password"; if( System.console() == null ) { final JPasswordField pf = new JPasswordField(); passwd = JOptionPane.showConfirmDialog( null, pf, message, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE ) == JOptionPane.OK_OPTION ? new String( pf.getPassword() ) : ""; } else passwd = new String( System.console().readPassword( "%s> ", message ) );` – krevelen Nov 10 '16 at 13:28
  • Hey, I exported the project as the runnable jar, and then run that jar from command line. but i'm still getting console null error. My other core java programs works well. This one is with selenium. Any advice for me ? – Abhigyan May 28 '17 at 12:25
  • @M.Justin Apparently, Woot4Moo in his 'highly insecure' comment was referring to the fact that the example not only failed to reset **passwordArray** to some garbage data but also created a **String** object instead of, say, iterating over the array with a **for-each** loop, etc. After all, this is exactly the reason why **readPassword()** returns a **char[]** rather than a **String**. – Igor Soudakevitch Oct 04 '17 at 11:58
  • 4
    There's not much sense in fretting over the internal memory security risk of a line that is literally printing the password out to the console. – Patrick Parker Oct 08 '17 at 17:10
8

You would use the Console class

char[] password = console.readPassword("Enter password");  
Arrays.fill(password, ' ');

By executing readPassword echoing is disabled. Also after the password is validated it is best to overwrite any values in the array.

If you run this from an ide it will fail, please see this explanation for a thorough answer: Explained

ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
Woot4Moo
  • 23,987
  • 16
  • 94
  • 151
  • 2
    @Woot4Moo: Could you please elaborate how "the accepted answer is insecure!". I see you're writing over the password after you read it in, but this just seems silly. The password is going to be in memory for some amount of time no matter what you do. Even if you didn't manually write over the memory holding the password, it would get garbage collected and the memory would be refilled with something else. Honestly, if someone has the ability to read arbitrary addresses in memory, I think you should have bigger concerns. – ArtOfWarfare Apr 20 '15 at 14:19
  • 1
    @ArtOfWarfare in the event the "answer" ever changes: http://stackoverflow.com/a/8138549/205426 the reason why it is insecure as I have stated is this: new String(passwordArray) a new String is allocated to the String Pool which "never" goes away during the lifetime of a JVM. To counter your statement about garbage collection, you may not be aware that the String class is "special" and doesn't get GCd. And yes I agree the password will be in memory for some amount of time, I just happen to reduce that amount of time as much as possible. – Woot4Moo Apr 20 '15 at 17:37
  • @ArtOfWarfare additionally, any system as complex as the JVM is going to have issues with it. There have been a myriad of vulnerabilities discovered in the almost 4 years since I made this post, against the JVM. So if you were running the JVM since 2011 in Java 6 I bet there was a "arbitrary memory" exploit – Woot4Moo Apr 20 '15 at 17:41
  • Overwriting the character values in the array is, at best, a band-aid. There is no guarantee that the contents of the "password" character array have not been copied around the heap a few times between the time that the password is read from the Console object and the time the `Arrays.fill()` method completes. The reality is that safe-handling of in-memory passwords in Java is simply *not possible*. – Christopher Schultz Apr 30 '19 at 14:43
  • 1
    1. Strings created with the ordinary constructor are not added to the pool. 2. Even strings added to the pool get garbage collected when no (other) reference exists. 3. In any real life application, something useful has to happen between the `readPassword` and the `fill` operation which will determine whether this effort has any point. Take JDBC drivers, for example. There is no way to pass the password to the driver without creating a string. While using an array and overwriting it after use, is an established best-effort practice, it should not be explained with wrong myths about string pool – Holger May 22 '23 at 15:24
3
Console console = System.console();
String username = console.readLine("Username: ");
char[] password = console.readPassword("Password: ");
user1525941
  • 33
  • 1
  • 1
  • 4
0

If you're dealing with a Java character array (such as password characters that you read from the console), you can convert it to a JRuby string with the following Ruby code:

# GIST: "pw_from_console.rb" under "https://gist.github.com/drhuffman12"

jconsole = Java::java.lang.System.console()
password = jconsole.readPassword()
ruby_string = ''
password.to_a.each {|c| ruby_string << c.chr}

# .. do something with 'password' variable ..    
puts "password_chars: #{password_chars.inspect}"
puts "password_string: #{password_string}"

See also "https://stackoverflow.com/a/27628738/4390019" and "https://stackoverflow.com/a/27628756/4390019"

Community
  • 1
  • 1
-1

The given code given will work absolutely fine if we run from console. and there is no package name in the class

You have to make sure where you have your ".class" file. because, if package name is given for the class, you have to make sure to keep the ".class" file inside the specified folder. For example, my package name is "src.main.code" , I have to create a code folder,inside main folder, inside src folder and put Test.class in code folder. then it will work perfectly.

Amulya Koppula
  • 150
  • 1
  • 5