Salt Generator

Random bytes for password hashing — measured in bits, not characters.

Your saltGenerated locally

 

Salt size
Bits, not characters — the same character count is a different size in every encoding.
Encoding and quantity
Encoding

Nothing mangles it. The safe default for a database column.Shorter. What most password-hashing formats print.Shorter still, and safe in a URL or a filename.

This salt generator produces random bytes in hex, Base64 or Base64URL, sized in bits. Before you copy one: if you hash passwords with bcrypt or Argon2, your library already made you a salt.

What a salt is, and what it is not

A salt generator produces a run of random bytes to mix into a password before it is hashed, so that two people with the same password end up with different hashes. The salt is then stored in the open, next to the hash it belongs to.

Not a password, not a key

This site generates four things that look alike and behave nothing alike. What separates a salt generator from the other three is that its output is not a secret.

A comparison of four kinds of random value. An API key is transmitted with every request, is secret, and is measured in characters. A secret key is never transmitted, is secret, and is measured in bits. A JWT secret is never transmitted, is secret, and its length is set by the signing algorithm. A salt is stored alongside the hash, is not secret at all, and is measured in bits. The salt is the outlier: it is the only one that is public by design.

An API key travels with every request and must stay secret. A secret key never moves and must stay secret. A salt sits in your database in plain sight — and that is correct.The four are separated here because their storage rules differ, not their character sets.

An API key is a credential you present. A secret key signs or encrypts. What a salt generator produces does neither: it carries no authority and unlocks nothing.

Why being public is fine

The job is to make one precomputed table useless. If everybody's password is hashed with different random bytes, the attacker's table for password123 matches nobody.

That works whether or not they can read it. They can — it is right there — and the table is still useless, because building one per salt means starting over for every account.

Which is why this salt generator shows no strength meter

Every other generator on this site bands its output by how long it would take to guess. A salt is never guessed, so a band would be answering a question nobody asked.

In its place is a count of how many salts you could draw before two came out the same, which is the property the size was chosen for.

You may not need this page

bcrypt already made you one

The most common reason to open a salt generator is to feed the result into a password hash. In the three algorithms you should be using, that step does not exist.

A bcrypt hash string such as dollar-2a-dollar-12-dollar-R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW breaks into four parts: the algorithm identifier 2a, the cost 12, then twenty-two characters that are the 128-bit salt, then thirty-one characters of hash. bcrypt generated that salt itself and stored it in the string, so there is nothing for you to supply.

A bcrypt hash is four parts, and the middle 22 characters are a 128-bit salt the library generated itself when it hashed the password.Format and example string from the bcrypt specification. scrypt and Argon2 store their salts the same way.

Paste a value from a salt generator into a bcrypt call and it is either ignored or it breaks the format. Nothing improves.

So when is it the right tool?

If you are hashing passwords with bcrypt, scrypt or Argon2 through a normal library, the library generates the salt and stores it in the hash, so you need nothing from this page. If you are calling PBKDF2, or building a scheme of your own, or writing a test fixture, the library asks you for a salt and sixteen random bytes is the answer. If you are looking for something to keep secret, a salt is the wrong tool and a secret key is the right one.

Three situations, three different answers. Only the middle one is a reason to generate a salt by hand.Quoting the OWASP Password Storage Cheat Sheet on what libraries handle for you.

PBKDF2 is the common case: most libraries take the salt as an argument and leave it to you, so a salt generator is exactly what you want. Beyond that it is per-record salts in schemes nobody handed you, and test fixtures that have to stay the same between runs.

OWASP puts it plainly

Their password storage guidance says most widely used libraries "automatically generate and manage salts internally, so application developers typically do not need to handle salt generation manually when using these libraries correctly".

A salt generator that does not tell you that is selling you something.

How big, and why

Sized for uniqueness, not for resistance

A key is sized so nobody can guess it. A salt generator sizes its output so no two are ever the same, which is a much easier target and a completely different calculation.

At 128 bits you could draw 2.2 × 10¹⁹ salts before a repeat became more likely than not. That is the number this salt generator reports, because it is the one that describes the job.

"16 characters" is not a salt size

Most competing pages give the answer in characters — sixteen to thirty-two is the usual advice. A character is not a unit of salt, and a salt generator that measures in them is being vague about the only number that matters.

What each size costs in each encoding
BitsBytesHexBase64Base64URL
1281632 chars24 chars22 chars
2563264 chars44 chars43 chars
51264128 chars88 chars86 chars

Read it backwards and the problem is obvious. Sixteen hex characters is 64 bits; sixteen Base64 characters is 96. Neither reaches 128, so the advice lands you short in two encodings out of three.

RFC 9106 answers it in bytes

The Argon2 specification says "16 bytes is RECOMMENDED for password hashing" — bytes, which survive the trip through any encoding. That is 128 bits, and it is the default here.

Storing and using it

One per password

RFC 9106 says the salt "SHOULD be unique for each password", and this is the rule worth remembering over everything else on this page.

A single salt shared across your whole database still defeats a generic rainbow table. It also lets an attacker build one table specific to you and attack every account at once, which is most of what salting was for. Run the salt generator again per password; it costs nothing.

You do not need to check for duplicates

A billion 128-bit salts collide with probability well under one in 10²⁰. The uniqueness check would be more likely to contain a bug than to ever fire, which is why this salt generator does not deduplicate a batch.

Store it beside the hash

A separate column, or inside the encoded hash string the way bcrypt does it. What matters is that you can find the right one when the user next logs in — without it the hash cannot be reproduced and the account is locked out permanently.

Choosing an encoding

Whichever your column accepts without transforming it. The salt generator offers hex as the safe default because nothing mangles it; Base64URL earns its place when the value ends up in a URL or a filename.

The bytes are identical in all three. Only the printed form changes, which is exactly why a salt generator should size in bits rather than characters.

Frequently asked questions

Is "16 characters" a salt size?

No, and the distinction matters. Sixteen hex characters is 64 bits; sixteen Base64 characters is 96. Neither reaches the 16 bytes RFC 9106 recommends for Argon2 — you need 32 hex characters or 24 Base64 ones for that. This tool is set in bits for exactly that reason, and shows the character count that follows.

Do I need a salt if I am using bcrypt?

No. bcrypt generates a 128-bit salt itself and stores it in the hash string it returns — it is the 22 characters after the cost field. Pasting a salt from this page into a bcrypt call either gets ignored or breaks the format. The same applies to scrypt and to Argon2 through a normal library.

Then who is this page for?

Anyone whose API asks for a salt: PBKDF2 in most libraries, a key derivation you are wiring together yourself, a per-record salt in a scheme nobody handed you. It is also useful for test fixtures, where you want a salt that stays the same across runs.

Why is there no strength meter?

Because a salt is not guessed. It is stored in plain sight next to the hash and the attacker is assumed to have it. What its size buys is uniqueness, so the figure shown is how many salts you could draw before a repeat became likely — 2.2 × 10¹⁹ at 128 bits.

Should I check my salts are unique before storing them?

Not at 128 bits. A billion salts drawn at that size collide with probability well under one in 10²⁰, which is far less likely than the check itself having a bug. Randomness gives you the uniqueness requirement for free, which is the whole reason salts are sized the way they are.

Can I use the same salt for every password?

No, and this is the one rule worth memorising. RFC 9106 says the salt "SHOULD be unique for each password". A shared salt still defeats a generic rainbow table, but it lets an attacker build one table for your database and break every account at once — most of what salting was for.

Which encoding should I pick?

Whichever your storage column takes without transformation. Hex is the safest default because nothing mangles it; Base64URL is worth it if the salt ends up in a URL or filename. The bytes are identical in all three — only the printed form changes.

Is the salt sent anywhere when I generate it?

No. It is produced by JavaScript already loaded in the page, using crypto.getRandomValues(), and nothing is transmitted, stored or logged. You can disconnect from the internet and the generator keeps working, which is the simplest way to check.

More free generators

Like this salt generator, every tool here runs locally in your browser, with no account and no limits.

Methodology

Last updated

How the bytes are produced

crypto.getRandomValues() fills a buffer of the requested size, which is then encoded, and Math.random() is never used. This salt generator shares its code path with the secret key generator — both are random bytes, and there is no reason to have two implementations of that.

How the collision figure is calculated

salts before a likely repeat ≈ 1.1774 × √(2bits)

The birthday bound, which is the point at which a repeat passes even odds. In a salt generator it replaces the strength band shown on the secret-bearing tools, because uniqueness rather than unguessability is what the size is chosen for.

Why the table is computed, not typed

The character counts above come from the same function the salt generator uses, and the unit tests assert them against real output for every size and encoding. A table someone typed would eventually drift from what the tool produces.

Why there is no bcrypt preset

Offering one would invite the mistake this page argues against. bcrypt builds its own salt and writes it into the hash, so a bcrypt-shaped button in a salt generator would encourage people to supply something the library neither wants nor accepts. A unit test asserts the preset list does not contain one.

Privacy

Nothing generated here is transmitted, written to storage, placed in the URL or attached to an analytics event. Load the page, disconnect from the internet, and it keeps working.