Hiding User Input for Sensitive Fields Like Passwords

When developing applications, whether for web, desktop, or mobile platforms, protecting sensitive information such as passwords during user input is crucial. Typically, login forms display input characters as asterisks or bullets to prevent shoulder surfing and other forms of eavesdropping.

This blog will explore why this practice is important, how it is implemented in various programming languages, and how to create cross-platform solutions for hiding sensitive inputs.

Password Masking

Passwords and other sensitive information must be hidden from prying eyes during input to protect users from potential onlookers. This form of protection is known as password masking.

Password Masking prevents anyone nearby from seeing the password being typed. Users can feel confident that their information is not exposed, which is particularly useful in shared or public spaces.

How do Applications Implement this?

Implementing input masking is relatively straightforward in modern programming languages. Most GUI frameworks and web development libraries provide built-in mechanisms to hide sensitive fields. Here are a few general methods:

  • HTML Input Fields: In web development, the <input type="password"> element hides the characters as asterisks.
  • Console Input Masking: In terminal-based or console applications, the input can be hidden using operating system-specific libraries and APIs.

Let’s implement password masking in C++, Java and, Python for terminal based applications, and for the Web applications using HTML and JS.

C++ Implementation

For terminal-based C++ applications, hiding user input requires working directly with the terminal’s settings. The termios library in Unix-like systems (macOS, Linux) allows developers to configure the terminal for password masking. Here’s an example:

//
//  main.cpp
//  Hide User Input
//
//  Created by Himanshu on 30/06/24.
//

#include <iostream>
#include <termios.h>
#include <unistd.h>

void setStdinEcho(bool enable = true) {
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    if (!enable) {
        tty.c_lflag &= ~ECHO;
    } else {
        tty.c_lflag |= ECHO;
    }
    (void)tcsetattr(STDIN_FILENO, TCSANOW, &tty);
}

int main() {
    char ch;
    std::string password;

    std::cout << "Enter password: ";
    setStdinEcho(false); // Disable terminal echo
    while((ch = getchar()) != '\n') { // Read until Enter is pressed
        if(ch != '\b') { // If not a backspace
            password += ch;
            std::cout << '*'; // Display asterisk instead of character
        } else if(!password.empty()) { // If backspace and string not empty
            password.pop_back(); // Remove last character
            std::cout << "\b \b"; // Erase last asterisk from console
        }
    }
    setStdinEcho(true); // Re-enable terminal echo

    std::cout << "\nPassword entered: " << password << std::endl;
    return 0;
}

This implementation disables terminal echo, preventing typed characters from being displayed. Instead, asterisks are printed for each character. After the password is entered, the terminal echo is restored.

To compile and execute this code, run the following commands

cd /path/to/your/file
g++ -o password_input password_input.cpp
./password_input

Explanation

  • Compilation Command:
    g++ -o password_input password_input.cpp
    • g++ is the compiler for C++. It is part of the GNU Compiler Collection (GCC), to compile and run the C++ program in the terminal.
    • -o password_input specifies the output executable name.
    • password_input.cpp is the name of the input source file.
  • Run Command:
    ./password_input
    • This runs the compiled executable.

This code will work on macOS and other Unix-like systems, providing a way to securely enter a password with hidden input.

Java Implementation

Java provides a straightforward solution for hiding passwords through the Console class. This is a secure and platform-independent approach, ideal for console-based applications.

import java.io.Console;

public class HidingUserInput {
    public static void main(String[] args) {
        Console console = System.console();
        if (console == null) {
            System.out.println("No console available");
            return;
        }

        char[] passwordArray = console.readPassword("Enter your password: ");
        String password = new String(passwordArray);

        System.out.println("Your entered password is: " + password);
    }
}

Java’s Console.readPassword() method disables input echo, ensuring no characters are displayed. The password is returned as a character array to minimize the risk of the sensitive data retained in memory.

To compile and execute this code, run the following commands

javac HidingUserInput.java
java HidingUserInput

Explanation

  1. Console Class: The Console class in Java provides methods to access the character-based console device, if any, associated with the current Java virtual machine (JVM).
  2. readPassword Method: This method reads a password or passphrase from the console with echoing disabled. This means that nothing will appear on the screen as the user types. The method returns a character array to improve security (you can clear the array immediately after use to minimize the lifetime of sensitive data in memory).
  3. Handling No Console Available: It’s important to note that the Console object may be null if the JVM is started in an environment where no console is available (for example, in an IDE like Eclipse). In such cases, password handling should be managed differently, potentially falling back to a GUI-based approach or another method that ensures the password is not displayed on the screen.

This approach is simple, secure, and utilizes Java’s standard libraries, making it ideal for console-based applications that need to handle sensitive information securely.

Python Implementation

Python simplifies the process using the built-in getpass module, which works across platforms.

import getpass

password = getpass.getpass("Enter password: ")
print("Password entered:", password)

The getpass.getpass() function hides the user input automatically, providing an efficient and secure way to handle sensitive information.

To execute this code, run the following command

python main.py

The getpass.getpass() function hides the user input automatically, providing an efficient and secure way to handle sensitive information.

Python Implementation for Displaying Masked Characters as asterisks

While the above implementations in C++, Java and, Python effectively hide user inputs, none of them display the entered characters as asterisks (or bullets) during input. Displaying asterisks for each character while still maintaining input masking is a more user-friendly approach.

Below, we’ll provide an improved Python solution that displays asterisks while the user types the password. However, implementing this feature depends on the platform, as some operating systems like Windows handle terminal input differently from Unix-like systems.

import sys
import tty
import termios
import getpass

def get_input(prompt):
    if sys.platform.startswith('win'):
        # For Windows, use getpass to hide input without showing asterisks
        return getpass.getpass(prompt)
    else:
        # For Unix-like systems (Linux, macOS), show asterisks during input
        print(prompt, end='', flush=True)
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(fd) # Set terminal to raw mode
            password = ''
            while True:
                ch = sys.stdin.read(1)
                if ch in ('\n', '\r'):  # Handle Enter key (newline or carriage return)
                    print(ch) # Move to the next line after password entry
                    return password
                elif ch == '\x7f':  # Handle backspace key
                    if len(password) > 0:
                        password = password[:-1] # Remove last character from password
                        # Overwrite the last asterisk on the screen
                        sys.stdout.write('\b \b')
                        sys.stdout.flush()
                else:
                    password += ch # Add typed character to password
                    print('*', end='', flush=True) # Show asterisk for each typed character
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) # Restore terminal settings

password = get_input("Enter password: ")
print(f"You entered: {password}")

To execute this code, run the following command

python main.py

On Unix-like systems (macOS and Linux), the tty and termios modules are used to handle input in raw mode, allowing each keystroke to be processed as it is typed. This enables the display of asterisks (*) for each typed character, while also handling backspaces appropriately.

However, Windows terminals don’t support the termios and tty modules, which are essential for manipulating terminal input/output behavior. For Windows, therefore, we have no option but to use the getpass module, which handles input hiding but does not allow for asterisks to be shown, as feedback during input. This is a deliberate design choice to prioritize security over user experience in password entry scenarios.

Web Implementation Using HTML and JavaScript

For web-based applications, hiding sensitive input like passwords is typically achieved using the <input> element with type="password". JavaScript and CSS can be used to further enhance this behavior.

Basic Input Form

Here is a basic HTML example of a password input field.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Password Input Example</title>
</head>
<body>

<form>
    <label for="password">Enter your password:</label>
    <input type="password" id="password" name="password">
</form>

</body>
</html>

In this example, when users type their passwords, the characters will automatically be hidden behind asterisks or bullets.

Custom Input Form

JavaScript can be used to toggle between showing and hiding the password.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Show/Hide Password</title>
</head>
<body>

<form>
    <label for="password">Enter your password:</label>
    <input type="password" id="password" name="password">
    <input type="checkbox" onclick="togglePassword()"> Show Password
</form>

<script>
    function togglePassword() {
        var passwordInput = document.getElementById("password");
        if (passwordInput.type === "password") {
            passwordInput.type = "text";
        } else {
            passwordInput.type = "password";
        }
    }
</script>

</body>
</html>

This JavaScript adds a checkbox that allows the user to toggle between viewing and hiding the password.

To view the above HTML, save the “Custom Input Form” in a file (any_name.html) and open it in a browser.

Hiding input for sensitive fields like passwords is essential for protecting user information and ensuring privacy. While most programming languages and platforms offer built-in methods to achieve this, understanding how to implement it effectively and securely across different environments can enhance the robustness of your applications. Whether you’re developing a terminal or a web application, it’s crucial to follow good practices, avoid exposing sensitive information in memory, and ensure cross-platform compatibility.

Leave a Reply

Your email address will not be published. Required fields are marked *