Accept Unicode passwords, count each code point as one character for length checks, and normalize with NFC before hashing. These are the points in NIST SP 800-63-4 Part B. Skipping normalization causes the classic bug where a password works on one device and fails on another.
What NIST 800-63B says
The draft guideline page we fetched states that each Unicode code point shall be counted as a single character when evaluating password length. It says printable ASCII and spaces should be accepted, that Unicode should be accepted, and that if Unicode is accepted, verifiers should apply NFC normalization before hashing.
It also says verifiers should permit a maximum length of at least 64 characters, and that they must request the password in full and verify the entire submitted value without truncating it.
Why normalization matters
The same visible character can be encoded more than one way. An accented letter may be one code point on one keyboard and a base letter plus a combining mark on another. They look identical and hash differently. A user who set their password on a phone then fails to log in on a laptop.
Normalizing to a single form before hashing removes the mismatch. NFC is the form the guideline names.
Where it goes wrong
- Hashing raw bytes with no normalization at signup, then normalizing at login, or the reverse. Both paths must do exactly the same thing.
- Counting bytes instead of characters, so a short password in a non-Latin script fails a length check or exceeds a limit early.
- A hashing function with an input limit, such as the 72 byte limit OWASP notes for bcrypt, truncating multi-byte passwords sooner than expected.
- Client side code that trims or alters whitespace.
- Database encodings that mangle characters.
A safe sequence
- Receive the password as UTF-8 text and reject invalid encodings.
- Check length by code points against your minimum and maximum.
- Normalize to NFC.
- Hash with your password hashing function.
- On login, repeat steps 1 and 3 before verifying.
Existing accounts
If you already store hashes of un-normalized passwords, you cannot normalize them retroactively. Normalize going forward, and at each successful login, if the verification works with the raw form, re-hash the normalized form. You may need to try both for a transition period.
Testing
Create test passwords with the same visible character in composed and decomposed forms. Confirm that both log in. Also test long passwords, emoji and a password with spaces. The cases that break your login will find you faster than users will.
Quick check
Is it fine to restrict passwords to ASCII?
NIST says Unicode should be accepted. Restricting to ASCII shuts out users who prefer passphrases in their own language, so avoid it unless you have a clear reason.
What maximum length should I set?
The guideline says verifiers should permit at least 64 characters. Pick a limit that bounds hashing cost but is not lower than that.
Safeguard's dependency scanning shows which authentication and hashing libraries your projects use, and the free scan at gold.safeguard.sh/scan is a quick start.
Sources
Last reviewed: 19 October 2026.