How to hash passwords on Linux

Passwords should never be stored as plain text. Whether we are talking about a web application or an operating system, they should always be in hash form (on Linux, for example, hashed passwords are stored in the /etc/shadow file). Hashing is the process through which, by the use of some complex algorithms, a password is turned into a different string. Such process is one-way: there is no way to revert an hashed password to its original, plain text form. Hashing often involves the use of random data as additional input for the hash algorithm, so that the same password, hashed two times, doesn’t produce the same result. This random data is called salt. In this tutorial we explore some methods we can use to hash passwords on Linux.

In this tutorial you will learn:

  • How to hash a password with the mkpasswd utility
  • How to hash a password with python and the crypt module
  • How to hash a password using openssl
How to hash passwords on Linux
How to hash passwords on Linux

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Distribution-independent
Software mkpasswd/python/openssl
Other None
Conventions # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux-commands to be executed as a regular non-privileged user

Hashing a password with mkpasswd

The first method to generate a password hash we discuss in this tutorial consists in the use of the mkpasswd utility, therefore the very first thing to do is to make sure it is installed on our system. The application is available in the official repositories of all the most used Linux distributions. To install it on Fedora we should run the following command:

$ sudo dnf install mkpasswd

On Debian and its many derivatives, instead, the application is part of the “whois” package (it should be installed by default anyway):

$ sudo apt install whois

Once the application is installed on our system we can use it to hash our plain password. The basic syntax is the following:

$ mkpasswd -m <hashing-algorithm>

With the -m option (short for --method) we specify what hashing algorithm we want to use. To obtain the list of the available ones we simply need to pass “help” as the argument of the option:

$ mkpasswd -m help
Available methods:
yescrypt        Yescrypt
gost-yescrypt   GOST Yescrypt
scrypt          scrypt
bcrypt          bcrypt
bcrypt-a        bcrypt (obsolete $2a$ version)
sha512crypt     SHA-512
sha256crypt     SHA-256
sunmd5          SunMD5
md5crypt        MD5
bsdicrypt       BSDI extended DES-based crypt(3)
descrypt        standard 56 bit DES-based crypt(3)
nt              NT-Hash




The recommended algorithm is sha512crypt (this is what is used on Linux). As soon as we run the command, we are prompted to enter the password we want to hash. The program works interactively for security reasons: if we had to enter the plain text password directly as argument of some option, it would be visible in the output of ps as part of the command, and in the shell history.

The hashed password is returned as the output of the command:

$ mkpasswd -m sha512crypt
Password:
$6$2sE/010goDuRSxxv$o18K52wor.wIwZp6aXXBC69phYwPQahKQo2ex8ce2.f0V9BtnYZc0KtTB0WGm2m5pNOcL1Ep3kgDWmJCz36B./

The salt is generated randomly, but to pass a value explicitly we can use the -s option (short for --salt).

If for some reason we still want to enter the password to be hashed in a non-interactive way (again, this is not recommended), we would use the --stdin option and some redirection magic:

$ mkpasswd -m sha512crypt --stdin <<< "plainpassword"

Hashing a password using Python

Another method we can use to generate a password hash on Linux is to use Python and the crypt module. As a first thing we import the module, then we use the crypt function included in it. The function has one mandatory argument, which is the plain text we want to encrypt; it returns the one-way hashed password, prepended by a salt. The hashing method can be passed explicitly as the second argument of the function, choosing one between the following (if one is not specified, the strongest available on the platform is used):

  • crypt.METHOD_SHA512
  • crypt.METHOD_SHA256
  • crypt.METHOD_BLOWFISH
  • crypt.METHOD_MD5
  • crypt.METHOD_CRYPT

The crypt.METHOD_SHA512 is the strongest. When used, a password is hashed with the sha512 function, with a salt of 16 characters.

In order to avoid passing the original password as part of the command, which will also be remembered in the python shell history, we should also import the getpass module, and make so that the password is requested interactively using the getpass() method included in it.

To generate our hashed password we would proceed as follows:

>>> import crypt
>>> import getpass
hashed_password = crypt.crypt(getpass.getpass(), crypt.METHOD_SHA512)
Password:

When working from a shell, the above example could be executed as a one-liner, invoking the Python interpreter with the -c option, which let us specify the command to be executed directly:

$ hashed_password="$(python3 -c 'import crypt; import getpass; print(crypt.crypt(getpass.getpass(), crypt.METHOD_SHA512))')"

In the example above you can notice that we used the print() function to print the generated hashed password, so that it will be used as he result of the command substitution, and will become the value of the hashed_password variable.

Hashing a password using openssl

The third and final method to generate a password hash we explore in this tutorial consists in the use of the openssl passwd command. By default the command uses the crypt algorithm to generate an hashed password. To use the sha512 algorithm, instead, we have to use the -6 option. Here is what we would write:

$ openssl passwd -6
Password:
Verifying - Password:
$6$82Bk5H60hZqXBSUp$GPdqJ1zNQOXwuXqUBBB59a4oaKah/HpR3nbiNrW1eXXPH48mTRZ3y6cOOMHnBtMjLF9IBfhDWfQMXMk8kM5kZ/




As you can see, for the security reasons we already mentioned, even with this method the password is requested interactively; additionally, we are also prompted to insert it a second time, to verify it. This behavior can be disabled using he --noverify option.

As happens with the other methods, the salt is generated automatically, but we have the chance to provide it directly using the --salt option:

$ openssl passwd -6 --salt <SALT>

We also have the chance to read the password from a file. All we have to do is to use the -in option, and pass the path of the file containing the password as argument. Supposing our password is written in the password.txt file, we would write:

$ openssl passwd -6 -in password.txt

When using this last option, we can provide more than one password in the file (one per line). They will be hashed separately and the result will be returned by the command.

Finally, if we don’t mind security implications, we can pass the password to be hashed directly as the last argument to the command:

$ openssl passwd -6 "plainpassword"

Closing thoughts

In this tutorial we saw three methods we can use to hash passwords on Linux. We saw how to use the mkpasswd utility, how to generate a password hash with the Python programming language using the crypt module, and, finally, how to perform the same operation using openssl.



Comments and Discussions
Linux Forum