5

for RHEL-8.10 with /etc/login.defs having ENCRYPT_METHOD SHA512 for my local ron account I set {as root} the password for it to also be just ron.

As such in /etc/shadow I have this:

ron:$6$NbmOz0kL4eKjJbwi$JE1.19BxJWh7cbZjmPPDrviuBV7l7h/Jlqz56CVqXmpttsXbz3YjhQ9Qm0CiYAY8oG4jkatTqXVgiAfbU66rR1:20377:0:99999:14:::

In trying to use the https://randommer.io/Hash/SHA512 webpage I have typed in ron for the password text and use this for the salt: NbmOz0kL4eKjJbwi and it gives me this

FD1C072B6D4578F30D5615F189D9317D8E24CAC2D60C0A6D280636C9035ED12A8C64F2C9F4D542C6BC4750373C6BA88745D2159428F04BB5FE068285F4B41D08

what am I doing wrong, and what is an easy/correct way whether it be in linux on the command line or using a free online tool to replicate the hash stored in /etc/shadow for when I have set the password to be just ron ?

1
  • 7
    For future readers. If you find yourself trying to manually check password hashes in /etc/shadow the chances are you're doing something wrong. In most common cases you should be invoking PAM for operations like login. Commented 2 days ago

3 Answers 3

13

The first visible difference is that the /etc/shadow file represents the hash result in Base64 while the website returns it in hexadecimal (base-16). The same bytes can be written in several different ways.

But the main difference is that the password hash in /etc/shadow is not produced by a single application of plain SHA512 – it's a sha512crypt hash.

The sha512crypt algorithm applies many iterations of SHA512 in a specific way, in an attempt to make hash calculation slower and resist brute force attacks. It's similar in principle to PBKDF2-SHA512.

(Plain SHA512 also doesn't define an exact method of including the salt – Base64-decode or not? prepended before the input? appended after? integrated in a different way? – the website you found just does whatever.)

The correct way to generate such hashes is to call crypt(3), but note that the $6$ prefix needs to be included as part of the salt string. On Linux the crypt() function can also generate Bcrypt $2b$ hashes and Yescrypt $y$ hashes, both of which are stronger than sha512crypt (see crypt(5) for an overview).

On older Linuxes, crypt() and libcrypt used to be part of libc.

The same crypt() also exists on other Unix-ish systems, e.g. OpenBSD, but with slightly varying interfaces and algorithms, e.g. some platforms might not have sha512crypt at all.

There's no built-in CLI tool for generating a hash for /etc/shadow, except by manually setting the password using passwd and then copying the resulting hash out of your /etc/shadow. But various tools named 'mkpasswd' do exist (though many are limited in which algorithms they support).

Python's passlib can also generate such hashes.

11
  • thanks. If I write some C code to play with this, do you know what the specific function names and .h files I would include to call sha512crypt to be able to manually replicate the hash observed in /etc/shadow ? I see a few under /usr/include/ Commented 2 days ago
  • I feel like if someone gave me the complete line out of /etc/shadow for an account... people tell me that's bad they can crack your password... I don't feel that's true; I can't even manually match the hash if I know what the password is to begin with. Commented 2 days ago
  • If I said hey internet here's my etcshadow you can't crack my password haha how would somebody do it? Commented 2 days ago
  • 3
    The fact that you don't know how to manually match the hash, doesn't mean other people don't know how to do that. Though most people would probably just run john (John the Ripper) or a similar tool against the hash. Commented 2 days ago
  • 2
    Also, a common mistake people make when hashing things for testing is echo hello | sha256sum -- this gives you the hash for hello followed by a newline. Commented 2 days ago
8

The standard library routine in C would be crypt(3). The second argument is the whole $6$NbmOz0kL4eKjJbwi string because that identifies the algorithm and the seed.

eg

// Compile with -lcrypt

#include <crypt.h>
#include <stdio.h>

void main()
{
  printf("%s\n",crypt("ron","$6$NbmOz0kL4eKjJbwi"));
}

So let's test this:

% gcc -o cr cr.c -lcrypt
% ./cr
$6$NbmOz0kL4eKjJbwi$JE1.19BxJWh7cbZjmPPDrviuBV7l7h/Jlqz56CVqXmpttsXbz3YjhQ9Qm0CiYAY8oG4jkatTqXVgiAfbU66rR1

This is also exposed to other languages; e.g. perl. So, for example, we can test this from the perl debugger

% perl -d -e 0
...
  DB<1> print crypt('ron','$6$NbmOz0kL4eKjJbwi')
$6$NbmOz0kL4eKjJbwi$JE1.19BxJWh7cbZjmPPDrviuBV7l7h/Jlqz56CVqXmpttsXbz3YjhQ9Qm0CiYAY8oG4jkatTqXVgiAfbU66rR1
4
  • +1, but why use the perl debugger when you can just use a perl one-liner: perl -l -e 'print crypt("ron",q($6$NbmOz0kL4eKjJbwi))' (note use of the q() quoting operator instead of ", otherwise perl would try to interpolate $Nbm... in the salt as a variable. see perldoc -f q). perl -l -e 'print crypt(shift, shift)' -- ron '$6$NbmOz0kL4eKjJbwi' works too. Commented 2 days ago
  • @cas because I was lazy and wanted to avoid any shell complications, just showing the actual commands. If I was writing a perl script then I wouldn't do the shift,shift or q() stuff, and the debugger was the quickest way of showing the library call without any of those complications. Commented 2 days ago
  • I probably wouldn't use shift, shift in a script, either. For a one-liner it's fine, and maybe in a sub - e.g. my ($v1,$v2) = (shift,shift) (@_[0,1] is shorter, but shift also removes them from @ARGV, @_, or the input array, which is useful). And q() is especially useful for one-liners, but is still useful in scripts - e.g. if the string you want to single-quote has several single-quotes in it and you don't want to have to escape them all. The fact that perl has several different quoting operators is really useful. Commented yesterday
  • +1; but I feel this answer could be even better if it mentioned Modular Crypt Format. Commented yesterday
5

You could use openssl's passwd subcommand:

$ printf %s ron | openssl passwd -6 -salt NbmOz0kL4eKjJbwi -stdin
$6$NbmOz0kL4eKjJbwi$JE1.19BxJWh7cbZjmPPDrviuBV7l7h/Jlqz56CVqXmpttsXbz3YjhQ9Qm0CiYAY8oG4jkatTqXVgiAfbU66rR1

You can change the number of rounds from its default (of 5000) with:

$ printf %s ron | openssl passwd -6 -salt 'rounds=99999$NbmOz0kL4eKjJbwi' -stdin
$6$rounds=99999$NbmOz0kL4eKjJbwi$.ePLjWxD4ZZBucJ7b7qxgu0KloBrOsflOkBz.054pdzhXm4TmBDZkpnZMVHf1yaHuGNBODZStLAQ0Z4O..zb9/

Same as:

$ printf %s ron | perl -lspe '$_=crypt$_,$salt' -- -salt='$6$rounds=99999$NbmOz0kL4eKjJbwi'
$6$rounds=99999$NbmOz0kL4eKjJbwi$.ePLjWxD4ZZBucJ7b7qxgu0KloBrOsflOkBz.054pdzhXm4TmBDZkpnZMVHf1yaHuGNBODZStLAQ0Z4O..zb9/

But without using the system's libc's crypt().

New contributor
matja is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.