En el post de hoy vamos a leer una cadena usando C (compatible con C++) pero no vamos a mostrarla, simplemente vamos a mostrar asteriscos o cualquier otro carácter mientras el usuario escribe.

Esto será hecho en C con MinGW en Windows pero lo he probado igual con Dev-C++. Al final tendremos un programa que va a solicitar una contraseña, no la va a mostrar y mostrará asteriscos en su lugar.

Pequeña nota de seguridad

Ya no deberíamos usar C para cosas de seguridad. Sí, sé que varias cosas están programadas con C (librerías, paquetes, núcleos de sistemas operativos) y que si lo usamos bien no habrá problema, pero ya no es recomendable.

Yo hago este tutorial por si tu profesor quiere enseñarte las bases y hacerte sufrir pensando en el algoritmo, pero ya no deberíamos manejar contraseñas con C al menos que sea para tareas o cosas divertidas.

Explicando el algoritmo

Necesitamos una forma de leer cada carácter o tecla presionada sin que el usuario presione Enter. En Windows existe getch, que nos da la tecla presionada, misma que fácilmente puede ser convertida a char.

Por cada carácter leído lo convertimos a cadena y lo concatenamos a la contraseña leída.

Estoy manejando 2 casos especiales: cuando se presiona la tecla de borrado y cuando se presiona Enter; en ese caso los códigos de las mismas son 8 y 13 respectivamente.

Leer contraseña en C sin mostrar caracteres escritos (mostrar asteriscos)

Cuando se presiona la tecla de borrado, eliminamos el último carácter de nuestra cadena. Y cuando se presiona Enter suponemos que el usuario terminó de escribir su contraseña.

Finalmente, cada que el usuario presiona una tecla limpiamos la pantalla y enmascaramos la cadena. Esto solo es necesario si enmascaras la cadena.

Nota: seguramente debe haber algunas teclas que no estoy tomando en cuenta, por ejemplo si el usuario quiere mover la posición del cursor con una tecla de dirección, o cosas de esas.

Leer contraseña en C

Vamos a la función. He encerrado todo el comportamiento en un método para poder invocarlo cuantas veces sea necesario.

Por cierto, esta función no regresa la cadena, simplemente coloca la contraseña en la cadena de destino que tú le indiques, por lo que debes declarar la string antes y enviar el apuntador a la misma.

void leerContrasenaSinMostrarla(char *palabraSecretaDestino)
{
    int caracterLeido = 0;
    char temporal[2];
    while (caracterLeido != TECLA_ENTER)
    {
        limpiarPantalla();
        printf("Ingresa tu palabra secreta: ");
        enmascaraCadena(palabraSecretaDestino, strlen(palabraSecretaDestino), MASCARA);
        caracterLeido = getch();
        // https://parzibyte.me/blog/2019/11/02/c-char-a-string/
        temporal[0] = caracterLeido;
        temporal[1] = '\0';
        if (caracterLeido == TECLA_BORRAR)
        {
            if (strlen(palabraSecretaDestino) > 0)
            {
                // https://parzibyte.me/blog/2022/03/23/eliminar-ultimo-caracter-cadena-c/
                palabraSecretaDestino[strlen(palabraSecretaDestino) - 1] = '\0';
            }
        }
        else if (caracterLeido != TECLA_ENTER)
        {
            strncat(palabraSecretaDestino, temporal, 1);
        }
    }
}

Hacemos un ciclo que se va a detener cuando el usuario presione Enter. Dentro del ciclo vemos si el usuario presionó el backspace para eliminar el último char, y en caso de que no, vemos si presionó algo distinto al Enter para concatenar ese carácter a la contraseña.

Fíjate en que tenemos dos funciones extras: la de enmascarar la cadena (que hace tiempo también hice con Arduino) y la que limpia la pantalla.

Enmascarar cadena

Para mostrar asteriscos en lugar de la cadena real, simplemente imprimimos un carácter desde 0 hasta la longitud de la cadena menos 1. Así:

void enmascaraCadena(char *cadena, int longitud, char mascara)
{
    int i = 0;
    for (i = 0; i < longitud; i++)
    {
        printf("%c", mascara);
    }
}

Limpiar pantalla

Existen varias formas de limpiar la pantalla, y también depende de la plataforma, terminal, sistema operativo y creo que también del estado de ánimo del programador.

Yo he usado la siguiente función:

void limpiarPantalla()
{

    // system("cls"); // Comentar en Linux y descomentar en Windows
    printf("\e[1;1H\e[2J"); // Comentar en Windows y descomentar en Linux
}

Por cierto este es un buen lugar para documentar que en ocasiones la limpieza de pantalla modificaba la cadena y no permitía eliminar el carácter. Todo muy raro, pero al final ya no me pasó.

Poniendo todo junto

Finalmente, para leer una cadena sin mostrarla, y en su lugar mostrar asteriscos ya sea en C o C++ tenemos el siguiente código junto con su implementación en el main:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>

#define TECLA_BORRAR 8
#define TECLA_ENTER 13
#define MAXIMA_LONGITUD_CADENA 1000
#define MASCARA '*'

/*
    https://parzibyte.me/blog
*/
void limpiarPantalla()
{

    // system("cls"); // Comentar en Linux y descomentar en Windows
    printf("\e[1;1H\e[2J"); // Comentar en Windows y descomentar en Linux
}

void enmascaraCadena(char *cadena, int longitud, char mascara)
{
    int i = 0;
    for (i = 0; i < longitud; i++)
    {
        printf("%c", mascara);
    }
}

void leerContrasenaSinMostrarla(char *palabraSecretaDestino)
{
    int caracterLeido = 0;
    char temporal[2];
    while (caracterLeido != TECLA_ENTER)
    {
        limpiarPantalla();
        printf("Ingresa tu palabra secreta: ");
        enmascaraCadena(palabraSecretaDestino, strlen(palabraSecretaDestino), MASCARA);
        caracterLeido = getch();
        // https://parzibyte.me/blog/2019/11/02/c-char-a-string/
        temporal[0] = caracterLeido;
        temporal[1] = '\0';
        if (caracterLeido == TECLA_BORRAR)
        {
            if (strlen(palabraSecretaDestino) > 0)
            {
                // https://parzibyte.me/blog/2022/03/23/eliminar-ultimo-caracter-cadena-c/
                palabraSecretaDestino[strlen(palabraSecretaDestino) - 1] = '\0';
            }
        }
        else if (caracterLeido != TECLA_ENTER)
        {
            strncat(palabraSecretaDestino, temporal, 1);
        }
    }
}

int main()
{
    char palabraSecreta[MAXIMA_LONGITUD_CADENA] = "";
    leerContrasenaSinMostrarla(palabraSecreta);
    // Nota: obviamente si no quieres mostrarla no la muestres, de todos modos la contraseña ya estará en palabraSecreta
    printf("\nLo que escribiste es: '%s'", palabraSecreta);
    return 0;
}

En el main defino mi cadena (línea 61) y la envío a la función leerContrasenaSinMostrarla. Cuando el usuario presione Enter, la función terminará y yo tendré la contraseña leída desde C.

Recuerda que tú decides qué hacer con la contraseña. Yo la muestro por motivos de prueba, pero tú puedes hacer cualquier otra cosa.

Para terminar te dejo con más tutoriales de C en mi blog.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Entradas recientes

Creador de credenciales web – Aplicación gratuita

Hoy te voy a presentar un creador de credenciales que acabo de programar y que…

17 horas hace

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

1 semana hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

1 semana hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

1 semana hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

1 semana hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

1 semana hace

Esta web usa cookies.