76

I would like to compute the bcrypt hash of my password.

Is there an open source command line tool that would do that ?

I would use this hash in the Syncthing configuration file (even if I know from here that I can reset the password by editing the config file to remove the user and password in the gui section, then restart Syncthing).

1

8 Answers 8

102

You can (ab)use htpasswd from apache-utils package, provided you have version 2.4 or higher.

htpasswd -bnBC 10 "" YOUR_PASSWORD | tr -d ':\n'

-b takes the password from the second command argument
-n prints the hash to stdout instead of writing it to a file
-B instructs to use bcrypt
-C 10 sets the bcrypt cost to 10

The bare htpasswd command outputs in format <name>:<hash> followed by two newlines. Hence the empty string for name and tr stripping the colon and newlines.

The command outputs bcrypt with $2y$ prefix, which may be problem for some uses, but can easily be fixed by another sed since the OpenBSD variant using $2a$ is compatible with the fixed crypt_blowfish variant using $2y$.

htpasswd -bnBC 10 "" YOUR_PASSWORD | tr -d ':\n' | sed 's/$2y/$2a/'

Link to htpasswd man page: https://httpd.apache.org/docs/2.4/programs/htpasswd.html
Details about bcrypt variants: https://stackoverflow.com/a/36225192/6732096

6
  • This version has a problem with the BCrypt implementation of Java Spring Security. The password to hash must be terminated with a null character. Spring Security seems to do it correctly. I think htpasswd is not doing this correctly.
    – k_o_
    Commented Apr 12, 2018 at 0:49
  • 1
    @k_o_: Can you be more specific on "has a problem"? All bcrypt implementations use the null-character terminator. Some, like py-bcrypt have even additional checks to ensure that null-character isn't a part of password. You can check the Apache implementation on GitHub. I'm using htpasswd with the additional sed to populate database records for multiple Spring applications without problems (that's actually how I come to the answer). Commented Apr 12, 2018 at 5:29
  • I was assuming that leaving out the null character was a problem of htpasswd to explain the different encodings between Spring and htpasswd. The output from bcrypt using the other answer's Python approach was producing the same results like in Spring, but htpasswd was not. Maybe also my htpasswd version is quite old, I think the binary was not updated since 2 years.
    – k_o_
    Commented Apr 12, 2018 at 21:13
  • 1
    There is yet another problem with Spring Security and BCrypt hashes generated with htpasswd. Spring Security (at least, certain versions) requires salt revision to be 'a' (so that the hashed password start with '$2a$'), but for me htpasswd generated revision 'y' ('$2y$....') and I was not able to find a way to specify the revision via command line. I then just abandoned htpasswd and generated the password using Spring Security code. Commented Jul 29, 2020 at 8:07
  • The tr can be replaced with sed -E '/^:/s/:(.*)$/\1/p;d' (at least, on linux) to avoid stripping the one newline you might want to keep.
    – phs
    Commented Feb 2, 2021 at 20:58
12

You can use a Python library. (This answer has been updated from the comments and for Python3 in 2024). On my Fedora system I did:

sudo dnf search bcrypt

(the sudo is just to avoid wasting space for a user dnf cache) and from the result I can see there is a Python3 package:

python3-bcrypt.x86_64 : Modern password hashing for your software and your servers

Install this and list the files in the package:

sudo dnf install python3-bcrypt
rpm -ql python3-bcrypt

This shows there is a file /usr/lib64/python*/site-packages/bcrypt/__init__.py so I can get the documentation with

pydoc bcrypt

This shows me enough to write the following command which will hash the string "password":

$ python -c 'import bcrypt; print(bcrypt.hashpw("password".encode(), bcrypt.gensalt()).decode())'
$2b$10$0W/r1Q43/tF0yW5PfBIB5Ouc7TRAG7TEWnm5OUt94iICgg2N8U.n6

For better security, you can get the program to prompt for the cleartext password and read it from the terminal without echoing:

python -c 'import bcrypt, getpass;
 print(bcrypt.hashpw(getpass.getpass().encode(), bcrypt.gensalt()).decode())'
3
  • 3
    As of April 2018 the parameter log_rounds seems to have changed to rounds making it python -c 'import bcrypt; print(bcrypt.hashpw("password", bcrypt.gensalt(rounds=10)))'.
    – HorstKevin
    Commented Apr 11, 2018 at 8:42
  • 1
    To make it interactive/slightly more secure, python -c "import bcrypt,getpass; print(bcrypt.hashpw(getpass.getpass().encode), bcrypt.gensalt()).decode())"you can even set it as an alias. Commented Apr 17 at 17:23
  • 1
    You've a few typos in there. I think this is what you meant: python -c "import bcrypt, getpass; print(bcrypt.hashpw(getpass.getpass().encode(), bcrypt.gensalt()).decode())" Commented Sep 8 at 18:01
6

This is relevant for FreeBSD, since htpasswd isn't available without installing apache. Building on @meuh's answer, here's how to use Python3 in FreeBSD to get a bcrypt hash of a password - for example, for basic auth in a traefik jail.

Note the following assumes a jail. Be careful with pip if this is the base OS. Adjust for version of Python3 depending on FreeBSD version and current Python3 versions available on it.

pkg install py37-pip
pip install bcrypt

And run, again adjusting for Python 3 version:

python3.7 -c 'import bcrypt; print(bcrypt.hashpw(b"PASSWORD", bcrypt.gensalt(rounds=15)).decode("ascii"))'

@Stuart Cardall rightly points out that this lands your password in history. "Left to the reader" to take this Python3 snippet and expand by a prompt for username and password, so that this information doesn't end up visible in ps output or history.

4

If you have a recent PHP installed, you can do it inline

echo -n "mynewpass" | php -r 'echo(password_hash(file_get_contents("php://stdin"), PASSWORD_BCRYPT)."\n");'

Just keep in mind the -n on echo, if your input may contain newlines, then you will need to trim those off first.

A more interactive version:

declare a;
printf '\nEnter the password:\n'
stty -echo
read -sr -- a;
stty +echo

printf '%s' "$a" | \
    php -r 'echo(password_hash(file_get_contents("php://stdin"), PASSWORD_BCRYPT)."\n");';
2

Additional to @Disassembler's answer:

  • it's not a good idea to pass passwords in from the command line (as the password could be viewable with ps)
  • 15 is a good balance for complexity / password generation speed

Wrapper script for htpasswd & bcrypt:

#!/bin/sh

## bcrypt passwd generator ##
#############################
CMD=$(which htpasswd 2>/dev/null)
OPTS="-nBC 15"
USERNAME=$1

usage() {
        local script=$(basename $0)
        cat <<EOF
$script: Generate Bcrypt Hashed Passwords using htpasswd

Usage: $script username
EOF
        exit 1
}

check_config() {
    if [ -z $CMD ]; then
        printf "Exiting: htpasswd is missing.\n"
        exit 1
    fi

    if [ -z "$USERNAME" ]; then
            usage
    fi
}

check_config $USERNAME
printf "Generating Bcrypt hash for username: $USERNAME\n\n"
$CMD $OPTS $USERNAME
exit $?
4
1

Following process worked for me!

I have installed httpd-tools using the following command in CentOS8

yum install httpd-tools -y

Then executed the htpasswd command like below:

htpasswd -bnBC 8 "" password | grep -oP '\$2[ayb]\$.{56}'

You may replace the password with your one :)

1

On ubuntu 20.04 I had to install python3-bcrypt package

apt install python3-bcrypt

and generated password using this script:

import getpass
import bcrypt

password = getpass.getpass("password: ")
hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
print(hashed_password.decode())

Script taken from here: https://computingforgeeks.com/secure-prometheus-server-with-basic-password-authentication/

0

On OpenBSD you would simply use the encrypt built-in command:

$ encrypt -b 9 -p
Enter string:
$2b$09$gj37KUAG4QhjKM5wqsPWv.zSzoqF2EH/PzF30.Vtpqiiz3lC4meEq

-b is the number of hashing rounds.
-p prompts the user for a string

When -p is not provided it reads the string from the standard input:

encrypt -b 15 < secret.txt
$2b$15$4j0cIg5WC3VPPjPIgojfNeNLXnpdYCKu19fPf90NTd6OYXCJmW7ry

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .