...
This compliant solution uses the Console.readPassword() method to obtain the password from the console.:
| Code Block | ||
|---|---|---|
| ||
class Password {
public static void main (String args[]) throws IOException {
Console c = System.console();
if (c == null) {
System.err.println("No console.");
System.exit(1);
}
String username = c.readLine("Enter your user name: ");
char[] password = c.readPassword("Enter your password: ");
if (!verify(username, password)) {
throw new SecurityException("Invalid Credentials");
}
// Clear the password
Arrays.fill(password, ' ');
}
// Dummy verify method, always returns true
private static final boolean verify(String username, char[] password) {
return true;
}
}
|
...
| Code Block | ||
|---|---|---|
| ||
void readData() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("file")));
// Read from the file
String data = br.readLine();
} |
The BufferedReader.readLine() method returns the sensitive data as a String object, which can persist long after the data is no longer needed. The BufferedReader.read(char[], int, int) method can read and populate a char array. However, it requires the programmer to manually clear the sensitive data in the array after use. Alternatively, even if the BufferedReader were to wrap a FileReader object, it would suffer from the same pitfalls.
...
| Code Block | ||
|---|---|---|
| ||
void readData() { ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024); try (FileChannel rdr = (new FileInputStream("file")).getChannel()) { while (rdr.read(buffer) > 0) { // Do something with the buffer buffer.clear(); } } catch (Throwable e) { // Handle error } } |
...
Bibliography
| [API 2013] | Class ByteBuffer |
| [Oracle 2012b2013b] | Reading ASCII Passwords from an InputStream Example (Java Cryptography Architecture [JCA] Reference Guide) |
| [Tutorials 20082013] | I/O from the Command Line |
...