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?
You can use following commands for the same:
openssl passwd -6 -salt xyz yourpass
Note: passing -1
will generate an MD5 password, -5
a SHA256 and -6
SHA512 (recommended)
mkpasswd --method=SHA-512 --stdin
The option --method
accepts md5
, sha-256
and sha-512
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
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.
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).
openssl passwd
documenation for anyone trying to figure out what the -1
option does.
python3 -c 'import crypt; print(crypt.crypt("test", crypt.mksalt(crypt.METHOD_SHA512)))'
- from related ServerFault question
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
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.')"
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.
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 :
).
crypt
module is deprecated in Python since version 3.11 and will be removed in version 3.13.
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))+"$")'
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)
Commented
Oct 5, 2018 at 6:10
openssl passwd -6 -salt $(head -c18 /dev/urandom | openssl base64)
Commented
May 1, 2020 at 19:55
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)
Commented
May 3, 2020 at 12:20
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.
Commented
May 3, 2020 at 12:42
-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...
Commented
May 4, 2020 at 15:25
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.
crypt.mksalt
does not work when generating passwords for /etc/shadow
. But @Alex131089's method works!
openssl
is a pretty universal tool.
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
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:::
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.
chpasswd
?
Commented
Sep 3, 2018 at 21:12
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.
Currently, I don't have enough reputation to comment.I created this password generator tool . It uses method no 1 described by Rahul Patil.