99tools

htpasswd Generator

runs in your browser

Make a .htpasswd file for Apache or nginx basic auth, with bcrypt hashing in your browser and the server config to go with it.

One per line, as user:password. Each step of the cost doubles the work, which is the point — it is what makes a stolen file slow to attack.

Users

about this tool

Users in, password file out

Write one user:password per line, choose a cost, generate. You get the .htpasswd file and the Apache or nginx config that points at it, since that is always the next question.

Hashed here, not on a server

The hashing runs in your browser and nothing is uploaded.

This is the whole reason to use this page rather than the first htpasswd generator a search turns up. Typing a real password into a page that hashes it server-side means handing that password to whoever runs the page — and the one thing you were trying to protect is the one thing you just gave away.

bcrypt only, on purpose

htpasswd can also write APR1, SHA1 and crypt. None of them should be used: crypt ignores everything after the eighth character, the SHA1 form is unsalted, and APR1 is a thousand rounds of MD5.

Apache has recommended bcrypt since 2.4 and it is what htpasswd -B produces. Offering the others would mostly serve to let somebody pick one, so they are not here — and the browser has no MD5 anyway, so APR1 would mean shipping an implementation of a broken hash to make a worse default available.

The output says $2y$ rather than $2b$ because that is what htpasswd writes. Same algorithm, same bytes; a file made here is indistinguishable from one made on the server.

Cost

Ten is the default, matching htpasswd -B.

Each step doubles the work. Twelve is four times slower than ten — for someone attacking a stolen copy of your file, and equally for your own server on every single request, because basic auth re-checks the password each time. Ten to twelve is the sensible range here. Higher belongs to hashes that get checked rarely, like a login form, not to one checked on every image on the page.

What gets refused

A username cannot contain a colon, and there is nothing to refuse: the first colon on a line is the separator, so admin:pw:extra is the user admin with the password pw:extra. The file format has no way to write it otherwise.

What is refused is a username the server would never match — one carrying a space, a control character, or one of the invisible characters that come along when a name is pasted out of a document or a chat window and read as admin everywhere a person can look. Those lines are left out with the reason and the line number, rather than written into a file that silently fails.

A duplicate username is kept but flagged — Apache uses the first and ignores the rest, which is rarely what somebody pasting a list intends.

bcrypt only hashes the first 72 bytes of a password. Anything past that is ignored entirely, so a longer password is no stronger, and the page says so rather than letting you believe otherwise.

Basic auth is not encryption

It base64-encodes the username and password and sends them on every request. That is trivially reversible by anyone watching the connection.

The password file protects you if the file is stolen. It does nothing if the connection is. Use HTTPS.

To look at an existing hash rather than make one, use the bcrypt tool.

questions

Are my passwords sent anywhere?
No. The hashing runs in your browser and nothing is uploaded or stored. That is the whole reason to use this rather than the first htpasswd site a search returns — typing a real password into a page that hashes it on a server means handing that password to the server.
Why is bcrypt the only option?
Because the others are weak and offering them mostly lets somebody pick one. htpasswd can also write APR1, SHA1 and crypt: crypt ignores everything after eight characters, the SHA1 form is unsalted, and APR1 is a thousand rounds of MD5. Apache has recommended bcrypt since 2.4, and it is what htpasswd -B produces.
What cost should I use?
Ten is the default and what htpasswd -B uses. Each step doubles the work, so twelve is four times slower than ten — for an attacker with your stolen file, and also for your server on every request. Ten to twelve suits basic auth; higher is for hashes checked rarely.
Why does the hash start $2y$ when bcrypt usually writes $2b$?
They are the same algorithm and the same output. htpasswd writes $2y$, so that is what this writes too, which keeps a generated file indistinguishable from one made on the server. Apache and nginx read both.
My username has a colon in it and the line does not work.
It cannot, and no tool can fix that — the first colon on a line is the separator, so whatever comes before it is the username and whatever follows is the password. admin:pw:extra is the user admin with the password pw:extra. A .htpasswd file has no way to write a username containing a colon. Everything else that would stop a line matching — a space, an invisible character pasted out of a document, a duplicate name, a password over 72 bytes — is called out beside the file, with the line number.
Does basic auth encrypt anything?
No. It base64-encodes the username and password and sends them on every request, which is reversible by anyone watching. Basic auth is only safe over HTTPS — the password file protects you if the file is stolen, not if the connection is.