169

I need to manually edit /etc/shadow to change the root password inside of a virtual machine image.

Is there a command-line tool that takes a password and generates an /etc/shadow compatible password hash on standard out?

Rahul
  • 13,589

10 Answers10

207

You can use following commands for the same:

Method 1 (md5, sha256, sha512)

openssl passwd -6 -salt xyz  yourpass

Note: passing -1 will generate an MD5 password, -5 a SHA256 and -6 SHA512 (recommended)

Method 2 (md5, sha256, sha512)

mkpasswd --method=SHA-512 --stdin

The option --method accepts md5, sha-256 and sha-512

Method 3 (des, md5, sha256, sha512)

As @tink suggested, we can update the password using chpasswd using:

echo "username:password" | chpasswd 

Or you can use the encrypted password with chpasswd. First generate it using this:

perl -e 'print crypt("YourPasswd", "salt", "sha512"),"\n"'

Then later you can use the generated password to update /etc/shadow:

echo "username:encryptedPassWd" | chpasswd -e

The encrypted password we can also use to create a new user with this password, for example:

useradd -p 'encryptedPassWd'  username
Axel Beckert
  • 287
  • 1
  • 12
Rahul Patil
  • 24,711
  • 6
    When using chpasswd -e, make sure to use single quotes on the string you echo in; otherwise, if there are $ or other special characters, they will not get treated literally. – Zags Oct 15 '14 at 19:28
  • 10
    Note that make of these will end up in your shell history. I would use openssl passwd -1 which 1) doesn't end up there and 2) generates a random salt for you (which doesn't end up in shell history, neither). – Ztyx Sep 22 '15 at 12:20
  • 2
    openssl passwd documenation for anyone trying to figure out what the -1 option does. – CivFan Oct 29 '15 at 21:55
  • 5
    For a SHA-512 hash: python3 -c 'import crypt; print(crypt.crypt("test", crypt.mksalt(crypt.METHOD_SHA512)))' - from related ServerFault question – CivFan Oct 29 '15 at 22:47
  • how does one make chpasswd output to stdout instead? I want to use longer hash with my puppet manifests. RHEL (not Debian or Ubuntu). – Felipe Alvarez Dec 11 '15 at 07:37
  • @FelipeAlvarez what you exactly want ? – Rahul Patil Dec 11 '15 at 11:06
  • @rahul sha512 salted password output to stdout for use with puppet manifest. – Felipe Alvarez Dec 12 '15 at 12:31
  • @FelipeAlvarez http://unix.stackexchange.com/questions/81240/manually-generate-password-for-etc-shadow/81248?noredirect=1#comment428419_81248 – Rahul Patil Dec 12 '15 at 17:26
  • 11
    Method 1) and 2) above uses MD5 for hashing. MD5 isn't considered best practise anymore as there has been hash collisions. Use method 3) or the one described in http://unix.stackexchange.com/a/198906/10911. – Ztyx Jan 11 '16 at 09:04
  • 1
    @Ztyx: Method 3 use the even worse DES method... – Gert van den Berg Dec 22 '17 at 13:49
  • All of the methods use problematic hashes: 1, 2 and 4 use MD5, method 3 uses the legacy DES method that only look at the first 8 characters of the password... – Gert van den Berg Dec 22 '17 at 13:59
  • Is there a way to check the hash being generated is correct? – CMCDragonkai Mar 08 '18 at 05:56
  • @CMCDragonkai You can try login with password which you encrypted. – Rahul Patil Mar 08 '18 at 09:41
  • Cannot do that in my situation. I'm in recovery USB. – CMCDragonkai Mar 08 '18 at 09:45
  • 1
    @Ztyx - Hash collisions are not a security risk for password hashing. Collisions are a risk for digital signatures and certificates. The fact that a hash is "broken" for collisions doesn't necessarily present any risk for pre-image attacks, which is what is important for passwords. While there are better hash functions for passwords, they're more geared around reducing risk of brute force searching than (slower to compute passwords) than they are being "more secure" for passwords. If the password is salted, the biggest risk with md5 for passwords is that it's very fast to compute. – Christopher Cashell May 31 '18 at 15:42
  • 1
    Note: My above comment is not meant as an endorsement for using MD5 for passwords. While a salted MD5 password may be secure, there are also significantly better options available for most cases. I just wanted to address the common confusion between collision attacks and pre-image attacks. – Christopher Cashell May 31 '18 at 15:43
  • @Ztyx, The salt in the shell history is not a problem. The salt should not be considered "secret". It just shouldn't be the same every time. So if you add users from a web-interface where you generate the passwords with openssl passwd -6 -salt someconstantstring THEN you're in trouble. (tables can be precomputed and if the file with the passwords leaks users may notice someone else has precisely the same password). – rew Sep 26 '19 at 11:30
  • To avoid having the salt and password show up in ps and having them stored in the shell history you can use this variant: openssl passwd -6 -salt $(head -c18 /dev/urandom | openssl base64) – maxschlepzig May 01 '20 at 19:53
  • openssl no longer supports passing -6 – rix Jun 24 '20 at 10:26
  • The perl example appears incorrect. I cannot find any version of perl that allows 3 arguments for crypt. But, on all GNU libc, you can do this: perl -E 'say crypt("password", q|$6$saltvalue|)' and the prefix $6$ in the salt gives you a sha512 result – dataless Nov 03 '21 at 18:47
45

On Ubuntu 12.04, there is mkpasswd (from the whois package): Overfeatured front end to crypt(3)

mkpasswd  -m sha-512 -S saltsalt -s <<< YourPass

Where:

  • -m = Compute the password using the TYPE method. If TYPE is help then the available methods are printed.
  • -S = salt used.

E.g.

$ mkpasswd -m help

-s = Read password from stdin
slm
  • 369,824
  • 15
    There's no need to specify the salt, mkpasswd takes care of generating a random one. – To마SE May 23 '16 at 20:03
  • 1
    No matter what, generated passwords from mkpasswd copied into the /etc/passwd always fail. Is there a way to check if the hash created by mkpasswd is correct? – CMCDragonkai Mar 08 '18 at 05:36
  • 3
    @CMCDragonkai: Wrong question. You need to ask what your system is expecting. – user3183018 Mar 08 '18 at 16:11
  • 1
    @To마SE: It is somtimes useful to control the salt. I have used it when testing hash generation of passwords for web app where I was storing the salt in a separate store. E.g. hashed password in MySQL DB, and per user salt in Redis. – user3183018 Mar 08 '18 at 16:13
26

This solution has the following benefits:

  • Nothing additional to install

  • Does not store the password in your shell history

  • Generates a random salt for you

  • Uses a modern, strong hashing algorithm, SHA-512

  • Re-prompts for the password to avoid mistakes.

     $ python3 -c "from getpass import getpass; from crypt import *; \
         p=getpass(); print('\n'+crypt(p, METHOD_SHA512)) \
         if p==getpass('Please repeat: ') else print('\nFailed repeating.')"
    

After Python 3.12

Edit: With the deprecation of the crypt module in Python 3.13, the following snippet can be used:

import os, base64, ctypes, getpass
salt = base64.b64encode(os.urandom(16), altchars=b"./").rstrip(b"=")
crypt = ctypes.CDLL("libcrypt.so.2").crypt
crypt.restype = ctypes.c_char_p
p=getpass.getpass()
if p==getpass.getpass("Please repeat: "):
    print("\n"+crypt(p.encode(), b"$6$"+salt).decode())
else:
    print("\nFailed repeating.")

it generates a random salt encoded to respect the [./0-9A-Za-Z] alphabet (B64, not to be mistaken with base64), loads the system crypt library (which the Python _crypt module is using) and call it's crypt function specifying the $6$ format (SHA512) plus the salt to compute the entry.

OpenSSL solution

However, OpenSSL often present on systems and providing a passwd command, seems to include newer algorithms since v1.1.1, so this might be easier to use.

For example (-6 here indicates algorithm 6, which is SHA512 ; salt is generated automatically):

$ openssl passwd -6
Password:
Verifying - Password:
$6$BIAw/F3wLlH4qofD$2dqhHKfCZNuLScGHKFdkEBmCwtTpInOZSwglqCAAeWgDVM7duqCZLJU69/Ie2LZHJMqUeT7mbx/.HLNrH50mk1

Be careful however with the -salt argument, because it doesn't allow empty salt and allows invalid values in the salt (like :).

References

u150825
  • 360
  • The crypt module is deprecated in Python since version 3.11 and will be removed in version 3.13. – eil Nov 17 '23 at 13:18
5

For those without Debian based systems. Python3 works just as well.

python3 -c 'import crypt, getpass; print(crypt.crypt(getpass.getpass()))'

getpass.getpass() will prompt you for a password on the command line.

Greg
  • 183
  • For some reason, using crypt.mksalt does not work when generating passwords for /etc/shadow. But @Alex131089's method works! –  Jul 22 '17 at 16:32
  • Just wasted 1.5h trying this method, before I noticed the comment. Can somebody remove it? I can't downvote yet. – Michał F Sep 29 '17 at 21:08
  • 2
    @MichałF it seems like this wasn't working because the salting wasn't done correctly. Thanks for pointing this out. I've removed the salt because the salting is dependent on OS and it's not practical to account for all ranges of OS in my answer. You should be using Method 1 outlined by @RahulPatil because it allows you to use salting and openssl is a pretty universal tool. – Greg Sep 29 '17 at 21:29
  • 1
    Not advisable, as it leaves your password in your shell history. – Mark Stosberg Mar 28 '18 at 15:00
  • I mean, you can always clear the cmd from your shell history – Greg Aug 21 '18 at 05:20
  • 1
    Provided a similar, but probably better answer here: https://stackoverflow.com/a/52096301/3628951 – AdamKalisz Aug 30 '18 at 11:50
  • The crypt module is deprecated in Python since version 3.11 and will be removed in version 3.13. – eil Nov 17 '23 at 13:19
5

None of the current methods are acceptable to me - They either pass the password on the command line (which ends up in my shell's history), require the installation of additional utilities (python3, makepasswd), use hard-coded salts or use old hashing techniques.

This method would generate SHA-512 hashes after prompting for the password and would use a random salt.

A method utilising Python 2 without any non-standard libraries:

python2 -c 'import crypt, getpass,os,base64; print crypt.crypt(getpass.getpass(), "$6$"+base64.b64encode(os.urandom(16))+"$")'

To do it without a prompt: (This will leave your password in the command history)

python2 -c 'import crypt, os,base64; print crypt.crypt("MyPassword", "$6$"+base64.b64encode(os.urandom(16))+"$")'
  • 3
    To avoid leaving the password in the command history, you can set (for bash, at least) the environment variable HISTCONTROL to 'ignorespace', and then add a leading space in front of the command. – adam820 Oct 04 '18 at 17:00
  • @adam820: That is one way... It would still it in the ps output in the fraction of a second that the command is running. (The safest remains to use the version that prompts for the password) – Gert van den Berg Oct 05 '18 at 06:10
  • Also with the openssl command you don't have to use a hard-coded salt nor pass the password on the command line, try e.g. this variant: openssl passwd -6 -salt $(head -c18 /dev/urandom | openssl base64) – maxschlepzig May 01 '20 at 19:55
  • @maxschlepzig Just leaving the "-salt" option off seems to result in a random salt as well. mkpasswd has other options, like specifying the number of rounds as well. Python3's crypt.mksalt also allows those to be specified. (I had a use case where Python 3 was unavailable, which is why this answer exists) – Gert van den Berg May 03 '20 at 12:20
  • @GertvandenBerg, the point is: the rationale in your first paragraph of your answer is incorrect. Counter example openssl: it doesn't require you to pass the password on the command line, it usually doesn't require the installation of additional utilities (i.e. which system doesn't have the openssl binary pre-installed but python ..) and it doesn't use hard-coded salts nor old hashing techniques. – maxschlepzig May 03 '20 at 12:42
  • @maxschlepzig For current OpenSSL versions... OpenSSL 1.1.0h did not support the -5 or -6 option. None of the answers at the time used those options at the time. Support for SHA-256 and SHA-512 hashes was only added in OpenSSL 1.1.1, which was released ~ a year after this answer... – Gert van den Berg May 04 '20 at 15:25
  • Perhaps it's time to update your rationale in your first paragraph then? – maxschlepzig May 04 '20 at 19:22
4

Yet another method to generate passwords, is using the openssl tool.

Generate MD5 passwords

openssl passwd -1 -salt SaltSalt SecretPassword
# output: $1$SaltSalt$FSYmvnuDuSP883uWgYBXW/

Generate DES passwords

openssl passwd -crypt -salt XR SuprScrt
# output: XR1dOp2EVMph2
3

The openssl and chpasswd -e pair didn't work in my case in RHEL6. Combining openssl passwd and usermod -p command did the job.

Generate the hash value of the password along with the salt value:

$ openssl passwd -1  -salt 5RPVAd clear-text-passwd43

$1$5RPVAd$vgsoSANybLDepv2ETcUH7.

Then, copy the encrypted string to usermod. Make sure to wrap it with single quotes.

$ usermod -p '$1$5RPVAd$vgsoSANybLDepv2ETcUH7.' root

Check it out in shadow file.

$ grep root /etc/shadow

root:$1$5RPVAd$vgsoSANybLDepv2ETcUH7.:17774:0:99999:7:::
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
2

Expanding a bit on the criticisms of u150825 and Gert van den Berg, I found myself needing something relatively flexible for different situations with different automation systems. I decided I would add to my own little library of useful scripts and write this. It uses only native libraries from python 2.7+, and works on python3 just as well.

You can pick it up here if you like. It's just as easy to drop this in your environment if you're needing to use it a lot, http hosted or whatever, and you can run it on any platform using whatever the default python interpreter you've got available to you is, pretty reliably counting on it working.

It defaults to prompting using getpass with prompts on stderr (allowing easy capture of stdout), but if you pipe a string to it it'll just reap from stdin. Depending on how you're going about this, it may not be showing up in command history, either, so just be cognizant of what it is you're working with. I like having a flexible tool that'll behave in an expected way, rather than having to rely on packages or python one-lining my way to victory 10 different ways.

  • Whether python in whatever version is already installed or not depends on the system. What exactly is the problem with chpasswd? – RalfFriedl Sep 03 '18 at 21:12
2

As many commenters have pointed out. Specifying your salt, let alone your password, is a security problem, because it makes reusing salts possible. Reuse of salts makes rainbow table attacks on your password hashes much more feasible, and it also makes it obvious which users share passwords with each other (isolating and highlighting likely less secure passwords such as 123456 or qwertyuiop).

You should not specify your password on the command line (because it is saved in shell history, and even if it's deleted, it could still reside for some time in the free space of your disk, especially if you're using a COW filesystem). You should not manually specify your salt at all. You can achieve this by simply using:

openssl passwd -6

(-6 specifies SHA512. Use -5 for SHA256. Avoid -1 for MD5, if possible.)

OpenSSL will ask you for your password via stdin twice, and generate a random salt for each input.

-2

Currently, I don't have enough reputation to comment.I created this password generator tool . It uses method no 1 described by Rahul Patil.

  • 2
    I don't think a web-based tool qualifies as a "command-line tool", unless you can show how it could be invoked from a CLI. – Jeff Schaller Jul 03 '20 at 00:11
  • It is invoking from Command line. you can compare "yourpass" generated from command line with the password generated from web tool. – Ammad Khalid Jul 03 '20 at 00:47
  • @JeffSchaller https://imgur.com/a/5MPjlnt – Ammad Khalid Jul 03 '20 at 00:49
  • Somebody will explain is there any reason to down my answer? because i can't comment or i made web base tool? thanks – Ammad Khalid Jul 12 '20 at 08:55
  • 3
    Nobody in their right mind would use a web-based tool to generate a password file entry, because then you'd have just handed the password to an unknown third party. Especially when every unix/linux system already contains the tools to generate it. – dataless Nov 02 '21 at 12:59