Need to hand a database a credential without ever typing the secret into a SQL statement? A MySQL password hash generator turns any password into the exact password hash that MySQL keeps for an account, so your scripts, tickets and chat logs only ever carry the hash. Paste the password, press the button, and you get a 41-character value you can drop straight into CREATE USER or ALTER USER.
How a MySQL Password Hash Generator Works
MySQL never stores the cleartext version of a password. Each row in the user table of the mysql database holds a hash value computed from the password, and the server compares that stored value with what the connecting client presents. A hash generator simply runs the same hashing algorithm in your browser, so you see the value the server would have created on its own. When you need to generate an sha3 hash, this free browser-based tool does it instantly.
There are two moments where the server touches a password. First comes authentication: when a client connects, the server checks that the supplied password produces a matching hash for the account. Second, a connected client with enough privileges can set or change the stored value, either with a statement such as SET PASSWORD or by calling the PASSWORD() function that older releases provided. The tool on this page covers the second moment: it gives you the stored value without a round trip to a live database.
Because the hashing runs in JavaScript inside your browser, nothing you type needs to leave the page. That matters for security, since the whole point of pre-hashing is to keep the plaintext out of places that were never meant to hold a secret.
What the generator needs from you
- The password you want to protect, typed or pasted as plain text.
- The authentication plugin you plan to use, which decides how the password hashing is done.
- The MySQL user name and the hostname if you want a ready-made SQL statement back, for example
'app_reader'@'localhost'.
How to Generate a MySQL Password Hash Step by Step
Whether you want to generate MySQL password values for a new application or convert an existing one, the routine is the same. Follow these steps in order: You can generate a pbkdf2 hash in seconds with a free tool that runs entirely in your browser.
- Choose a strong password: at least 16 characters, mixed case, digits and symbols, ideally a random password from a generator rather than something you invented.
- Select the
mysql_native_passwordplugin if the target application needs it, orcaching_sha2_passwordfor a modern version. - Paste the password and press the button to produce the hash.
- Copy the result into
CREATE USER 'name'@'host' IDENTIFIED WITH mysql_native_password AS '*HASH'. - Run the statement as a privileged user, then store the actual password in your secrets manager so the client can still login. Never leave the secret only inside the hash; a hash cannot be reversed, and the user table will not give it back.
That is the whole workflow. If you prefer working outside the page, the same value comes out of a short Python script, a one-line shell helper in command line mode, or an interactive mode prompt that asks for the password and prints the hash. Every route should produce an identical string for an identical input.
The mysql_native_password Hash Format
The mysql_native_password format is the 4.1 method, and it is still the one most people mean by a MySQL hash. It applies SHA1 twice and prefixes the result with an asterisk:
$$\text{hash} = \texttt{*} + \operatorname{HEX}\big(\operatorname{SHA1}(\operatorname{SHA1}(\text{password}))\big)$$
The inner SHA1 turns the password into 20 raw bytes. The outer one hashes those 20 bytes again, producing another 20 bytes, which are written as 40 uppercase hexadecimal characters. Add the leading * and you reach 41 characters, which is why the original manual describes a 41-byte value. There is no salt, so two accounts with the same password end up with the same hash, a property worth remembering when you pick a mysql password hash for a shared service.
A worked example you can reproduce
Take the password Kestrel#4172-Lantern, a 20-character value. Hashing it once gives the intermediate digest below, and hashing that digest again gives the stored value:
| Step | Operation | Result |
|---|---|---|
| 1 | Plain password | Kestrel#4172-Lantern |
| 2 | First SHA1 (20 bytes) | 2f49e356e813bc669cad08bb3c7555f30f283f11 |
| 3 | Second SHA1 over those bytes | 0eeda8d4ed055d6bb062780e01156290d99a4f50 |
| 4 | Uppercase and add the asterisk | *0EEDA8D4ED055D6BB062780E01156290D99A4F50 |
The final line is what lands in the authentication_string column, and it is the value you would send in IDENTIFIED WITH mysql_native_password AS '*0EEDA8D4ED055D6BB062780E01156290D99A4F50'. Run the same password through any compliant hash generator and you should see the same 41 characters, which makes this a handy fixture for a cryptographic sanity check.
caching_sha2_password and Other MySQL Password Hashing Plugins
MySQL 8.0 changed the default. Understanding the difference helps you decide which output you really need from a MySQL password generator.
How caching_sha2_password stores a password
The caching_sha2_password plugin uses SHA256 with a random salt and many rounds, so the stored string is much longer than the 41-character format and differs every time you hash the same input. That makes it far harder to attack, but it also means a page cannot show one fixed answer for a given password. It is the default authentication plugin from MySQL 8.0 onward.
Why the first login needs TLS or an RSA key
A caching_sha2_password hash from this page still needs a TLS connection or an RSA key exchange on the first connection. An older driver or legacy connector cannot manage that, which is the usual reason to generate the native hash instead.
Migrating users away from the legacy plugin
If a legacy application still needs mysql_native_password, treat that as technical debt. Check each MySQL user, upgrade the connector, then switch the account with ALTER USER ... IDENTIFIED WITH caching_sha2_password BY '...'. Plan the upgrade before the plugin disappears from your server.
MySQL Password Hashing by Version: pre-4.1 to 9.0
The stored format has changed several times, and each change affects compatibility with old clients. Reading a hash correctly starts with knowing its length and its first character.
| Format | Length | How to recognise it | Status |
|---|---|---|---|
pre-4.1 (OLD_PASSWORD()) | 16-byte | 16 hexadecimal characters, no asterisk | Removed in MySQL 5.7.5 |
4.1 / mysql_native_password | 41-byte | Starts with * | Deprecated in 8.0.34, off by default in 8.4 |
caching_sha2_password | 70 bytes | Starts with $A$005$ | Default in MySQL 8.0 |
| Any plugin on MySQL 9.0 | n/a | mysql_native_password no longer loads | Plugin removed |
The pre-4.1 method
The original pre-4.1 method produced a short 16-hex-digit value, and the OLD_PASSWORD() function was added so administrators could still generate it. Anyone still holding a pre-4.1 value should treat it as deprecated: the secure_auth setting is on by default, so those accounts cannot connect. Support was dropped in MySQL 5.7.5, together with the old_passwords variable. The manual on migrating away from pre-4.1 hashes is the right place to start.
From MySQL 5.7 to MySQL 8.0 and 9.0
A MySQL 5.7 server still defaults to the 4.1 format and accepts the PASSWORD() function; MySQL 8.0 removed that PASSWORD() function entirely and switched the default plugin. On MySQL 8.4 the legacy plugin is disabled until you enable it, and on MySQL 9.0 it is gone, so a MySQL 5 era application must change its authentication setup before the upgrade. Those pre-4.1 leftovers deserve a look too, because an account that cannot authenticate after a version bump is the classic outage. This authentication timeline is the single most useful fact when you decide which plugin to generate.
Using a Hash in CREATE USER, ALTER USER and GRANT
Most of the time you should write IDENTIFIED BY 'password' and let the server do the hashing. The server rewrites the password in CREATE USER, ALTER USER and SET PASSWORD statements before they reach the query log and the binary log, and the mysql client skips such lines in its history file. A hash is the better choice when the SQL travels somewhere that has no such protection.
-- new account
CREATE USER 'app_reader'@'localhost'
IDENTIFIED WITH mysql_native_password
AS '*0EEDA8D4ED055D6BB062780E01156290D99A4F50';
-- change an existing account
ALTER USER 'app_reader'@'localhost'
IDENTIFIED WITH mysql_native_password
AS '*0EEDA8D4ED055D6BB062780E01156290D99A4F50';Notice that IDENTIFIED WITH carries the plugin name and AS carries the stored value, while IDENTIFIED BY takes a clear password. Mixing them up is the usual typo. Older tutorials also show GRANT ... IDENTIFIED BY PASSWORD '*HASH', a form that was deprecated long ago. On modern servers create the account first, then run a separate GRANT. The same pattern applies to the root account: use 'root'@'localhost' only on the machine itself, since localhost and a wildcard host are different accounts.
When to Pre-Hash a MySQL Password
Pre-hashing earns its keep in places where plaintext tends to leak:
- Provisioning scripts and init files baked into a Docker image.
- Flyway or Liquibase migrations that live in version control.
- Config management with Ansible, Terraform or Puppet, which like to echo rendered templates into CI output and state files.
- Handing SQL to another team, so only the application's secret store ever sees the real password.
- Query consoles, ticket comments and chat logs that do not know they should redact
IDENTIFIED BY.
One caution: a stored hash is still a secret. Anyone holding it can mount an offline guessing attack, and because the 4.1 format has no salt, common passwords fall quickly. A long random password with high entropy makes that attack pointless, while a guessable one does not.
Testing with a MySQL Hash Generator
If you maintain a MySQL password hash creator of your own, or implement the same algorithm in an application, a reference page gives you something to compare against. Web developers and programmers use it for cross-browser testing of their own hashing code, checking that a double SHA1 routine returns the page's output for the Kestrel#4172-Lantern fixture. You can write two kinds of test cases: one that checks a known password produces the right hash, and one that checks a stored hash matches its source password. The page cannot recover a forgotten password, because the hash is one-way, but you can hash a guess and compare it with the stored value, or simply set a new one.
Pre-Hashing a Docker Seed Password with a MySQL Hash Generator
Marta Ilves maintains a staging stack where a MySQL 5.7 container loads seed.sql from Git on every rebuild. Her reviewer has already flagged the plain IDENTIFIED BY line, so she opens the page and pastes the new reporting-account password, Orchard-Wren-5093, with the mysql_native_password plugin selected because the container's older driver cannot negotiate anything newer.
The tool returns *CB676E157A2305671687692E58FC4AB7A2E899F0. She counts it: an asterisk plus 40 hexadecimal characters is 41, the length the 4.1 format must have, so the paste is intact. Then she rewrites the seed line as CREATE USER 'reporting'@'%' IDENTIFIED WITH mysql_native_password AS '*CB676E...F0' and commits it, while the real password goes to the team vault.
Before merging she rebuilds the container and logs in as reporting with the vault value. The login succeeds, which confirms the hash matches. She then changes one character, Orchard-Wren-5094, and the server answers with ERROR 1045, exactly what a different hash should do.
The result also drives her next action. Her reviewer's checklist cites MySQL 8.0.34, where mysql_native_password was deprecated, so she opens a ticket to move the staging image to 8.4 and switch the account to caching_sha2_password once the driver upgrade lands. Until then, the repository holds a salt-free hash of a 17-character random password, which is acceptable because an offline guessing attack against it is impractical, and the plaintext never touches Git history, the CI log or the binary log.
Generate the Same Hash from the Command Line
A browser page is convenient, but a team that provisions many accounts usually wants the same result from a script. The algorithm is short enough to fit in a few lines of Python, and the output must match the page character for character:
import hashlib
def mysql_native_hash(password):
inner = hashlib.sha1(password.encode("utf-8")).digest()
return "*" + hashlib.sha1(inner).hexdigest().upper()
print(mysql_native_hash("Kestrel#4172-Lantern"))
# *0EEDA8D4ED055D6BB062780E01156290D99A4F50Wrap that function in a small utility and you have a password-hash helper for your own pipeline. A good one accepts the password as an argument or, when none is given, drops into interactive mode and asks for it, so the secret never appears in your shell history. Add a flag that creates a random value of any length and you have a full MySQL password and hash generator: it picks a random password, prints it once for the secret store, and prints the matching hash for the SQL file.
Two habits keep this safe. First, read the password from an environment variable or a prompt rather than a literal argument, because process lists expose arguments. Second, generate with a cryptographically secure source, for example secrets.token_urlsafe(24), never a general-purpose random function. A weak source quietly destroys the entropy that makes the account safe, and no later hashing step can repair that.
Reading and Verifying a Stored Hash
Sooner or later you will inspect a MySQL user that someone else created. Query the account row and look at the authentication_string column together with the plugin column. If the plugin reads mysql_native_password and the value starts with an asterisk followed by 40 hexadecimal characters, you are looking at the 4.1 format, and you can check a candidate password by hashing it and comparing the strings.
- A value of 41 characters starting with
*means the 4.1 method. - A value of 16 characters with no asterisk means the pre-4.1 method, which current servers refuse.
- A long value beginning with
$A$belongs tocaching_sha2_passwordand cannot be recomputed without its stored salt. - An empty value means the account has no password at all, a security problem to fix at once.
Comparing hashes this way is also how you confirm a migration. Hash the known password with the page, hash it again with your script, and compare both to the row. Three matching strings tell you the hashing chain is intact from the browser to the database, and a mismatch usually points at stray whitespace, a different character encoding, or a trailing newline pasted along with the secret.
Security Practices for Any MySQL Password Hash Generator
Pre-hashing changes where the secret lives; it does not remove the need to protect it. Keep these habits in mind whenever you create a hash for a production account:
- Prefer
caching_sha2_passwordfor every new account, and keepmysql_native_passwordonly for the one application that truly needs it. - Restrict who can read the user table; the stored value is enough for an offline attack against a weak password.
- Use a unique strong password per service so a leaked hash exposes one account, not five.
- Rotate credentials when staff leave, and rotate them again if a repository containing a hash was ever public.
- Limit each user to the privileges it needs, because a safe hash on an over-privileged account is still a risk.
The page you are using hashes in the browser, yet you should still avoid typing a real production secret on any shared or untrusted machine. Generate a throwaway value, test your statement against a staging server, and only then repeat the steps with the real one. For long-lived systems, this is a good moment to review the version matrix above and plan the next upgrade, since hashing choices made today decide which client libraries keep working in two years.
MariaDB Compatibility for a MySQL Hash
MariaDB is different
MariaDB shares the 41-character native format, but it ships its own plugins and keeps mysql_native_password as a supported default. A hash generated for one engine is not guaranteed to be accepted by the other with a newer plugin, so test against the target MariaDB release.
Common errors with a pasted MySQL password hash
- ERROR 1819: the password validation component rejects the clear password. Pre-hashed values skip that check, so confirm the policy still holds elsewhere.
- ERROR 1045: access denied, usually a wrong password or a mismatched host.
- A pasted hash missing its asterisk is read as a 16-byte pre-4.1 value and refused.
Choosing a Strong Password Before You Hash It
Hashing protects storage; it does not rescue a weak input, and it is one-way, so the same password always gives the same 41-character hash but the hash never gives the password back. Pick at least 16 characters, avoid dictionary words and years, and create the value with a generator. Then generate the hash, load it with your SQL, and keep the real password in a secret manager where only the application can read it.
Frequently Asked Questions
- What is this hash format used for?
- This is the exact format MySQL's built-in PASSWORD() function has produced since MySQL 4.1 -- a double SHA-1 digest, uppercase hex, prefixed with an asterisk. It's used internally by MySQL for replication authentication and legacy account password storage, not for hashing passwords inside your own application.
- Why double-hash with SHA-1 instead of hashing once?
- The double-hash construction (SHA1(SHA1(password))) was specifically designed so that MySQL's server-side authentication challenge-response protocol never needs to see the plain SHA1(password) value, which alone would be enough to authenticate as that user -- it's a protocol design choice from the era, not a modern security best practice by today's standards.
- Is this format secure for storing application passwords?
- No -- like plain SHA-1 or MD5, this is a fast hash with no salt and no iteration count, making it fast to brute-force with modern hardware. It exists here purely to replicate MySQL's own internal authentication format, which you may need for MySQL replication setup or legacy account migration -- not as a recommendation for hashing passwords in your own application (use bcrypt or Argon2 for that).
- Does this match what CREATE USER ... IDENTIFIED BY PASSWORD produces?
- Yes, for the legacy mysql_native_password authentication plugin -- this is exactly the hash format stored in the mysql.user table's authentication_string column when using that plugin. Newer MySQL versions default to caching_sha2_password, which uses a different (unpublished, salted) scheme this tool does not replicate.
- Is my password sent anywhere?
- No. The hash is computed entirely in your browser using the Web Crypto API -- nothing is transmitted to a server or stored.