About readsecret

Readsecret is a simple self-contained C (or C++) library intended to be used on Unix and Unix-like operating systems that need to read a password or other textual secret typed in by the user while in a text-mode environment, such as from a console or shell.

It is similar in purpose to the GNU getpass() function; but it has more features, is more secure, and more robust against failures.

  • Can manage timed inputs
  • Handles interrupts and signals more robustly
  • Can prevent core-file dumping during entry to avoid secret disclosure
  • Securely overwrites memory, better than memset()
  • Reentrant and state-free
  • Conservative error handling and reporting

Download source code

The current version is 1.0. You can browse files for 1.0, or download just the most important source code files as:

Or download a tarball of everything: readsecret-1.0.tar.bz2

Git access: The code is also available with git at https://github.com/dmeranda/readsecret". You can clone the source code with:

    $ git clone https://github.com/dmeranda/readsecret

Compiling and installing

It is assumed you have an ANSI C compiler, as well as a POSIX operating system environment (e.g., Linux or Unix compatible environment).

The included "build script" use the SCons tool. The Makefile is just a front-end to SCons, so you will need SCons to use the Makefile. You can obtain SCons from www.scons.org. Most Linux distributions will provide SCons as an (optional) installable package.

To compile, type:

    $ scons -Q

To install the library and associated header file type:

    $ scons -Q install

or to install to a location other than the default "/usr/local", use:

    $ scons -Q prefix=/some/directory install

Using readsecret

For your programs, you can just include the readsecret source code into your own sources. But if you wish to use readsecret as a library you will need to install the library and header file as noted above. Your C source code should include the readsecret.h header file,

    #include "readsecret.h"

Then you just need to link with the libreadsecret library. On some platforms you may also need to link against additional system libraries (to get access to the POSIX real-time timers). Under Linux you will need to link with "librt". For example:

    $ gcc -o myprogram myprogram.c \
          -I /usr/local/include \
          -L /usr/local/lib -l readsecret -l rt

Licensing

This is FREE SOFTWARE. This code, comprising all the files listed above in the Download section, is hereby released into the Public Domain.

As some countries or jurisdictions may not legally acknowledge Public Domain, I also hereby release this under the terms of the Creative Commons CC0 1.0 Universal (CC0 1.0) license, which can be read in full at: creativecommons.org

Example usage

Read the documentation for complete details.

The following example C code will use this readsecret library to read typed text secretly (not being displayed) from the command line and then print it back out.

Simple example
#include <stdio.h>
#include "readsecret.h"

int main()
{
    char pass[ 40 ];
    rsecret_error_ty rc;

    rc = rsecret_get_secret_from_tty( pass, sizeof(pass),
                                      "Enter password: " );
    if( rc == RSECRET_SUCCESS ) {
        /* Do something with the password */
        printf( "Your password is: %s\n", pass );
    }
    return 0;
}

This next example shows a more involved use, and is also more secure in that it tries to prevent accidental leakage of the password.

A better example
#include <stdio.h>
#include <time.h>
#include "readsecret.h"

int main( int argc, char* argv[] )
{
    void* corefile_state;
    struct timespec timeout;

    timeout.tv_sec = 30;  /* A 30.0 second timeout */
    timeout.tv_nsec = 0;

    corefile_state = rsecret_inhibit_corefiles();
    {
        char pass[ 40 ];
        rsecret_error_ty rc;

        rc = rsecret_get_secret_from_tty_timed(
                 pass, sizeof(pass),
                 "Enter password: ",
                 timeout );
        if( rc == RSECRET_SUCCESS ) {
            /* Do something with the password */
            void* hash = hash_password( pass );
        }
        else {
            printf( "Could not read password: %s\n",
                    rsecret_strerror( rc ) );
        }
        rsecret_overwrite_buffer( pass, sizeof(pass) );
    }
    rsecret_restore_corefiles( corefile_state );
    return 0;
}