Is Your Password Really Secure? Hashing, Salting, and WebAuthn Explained

This article examines why passwords are often insecure, explains how they should be stored using hash algorithms and salts, outlines common password‑weaknesses and system vulnerabilities, and introduces FIDO/WebAuthn as a modern, password‑less authentication solution.

ELab Team
ELab Team
ELab Team
Is Your Password Really Secure? Hashing, Salting, and WebAuthn Explained

Is Your Password Secure?

How to tell if your password has been leaked? Some security vendors regularly collect breached credential data. Using Avast’s HackCheck you can enter an email address and see whether associated accounts or passwords have been exposed. In the author’s test, passwords from Adobe, CSDN and JD.com were found; Adobe and JD.com leaked only hashed passwords, while CSDN leaked a clear‑text password.

If you save passwords in Chrome, enable the security warning option in Chrome’s settings; Chrome will alert you when a saved password appears in a breach.

Why Your Password Might Be Insecure

Password Storage

Passwords should be stored encrypted in a database. Unfortunately many small‑scale projects store passwords in plain text. Typically a hash algorithm (e.g., MD5) is applied during registration and the resulting hash is stored:

MD5("password") = 5f4dcc3b5aa765d61d8327deb882cf99

During login the entered password is hashed again and compared with the stored hash. Hashes are one‑way, making it impossible to recover the original password from the hash alone, which protects the password even if the database is compromised.

However, attackers can use rainbow tables to reverse common hashes. Adding a random salt per user mitigates this risk:

MD5("password32142") = 970e6155f135079c9c1b9d3302b957b5

Modern systems prefer stronger algorithms such as bcrypt, which automatically generates a random salt and produces a unique hash even for identical passwords.

Weak Passwords

Do not use personal information (birthdate, phone number, name) as passwords.

Avoid reusing the same password across multiple services.

Do not use simple words or repetitive characters; combine uppercase, lowercase, numbers, and symbols.

Regularly change passwords to reduce risk from data‑leak incidents.

In practice, most users violate these rules, creating passwords that are vulnerable to disclosure.

Business System Vulnerabilities

All software is written by humans, so bugs and insecure practices are inevitable. Even large companies like Meta, Twitter, and the Chinese BAT have suffered password leaks. Supply‑chain attacks (e.g., XcodeGhost, Docker Hub breach) further increase risk.

In the author’s own project, a downstream service logged user passwords in plain text, violating data‑classification policies that require L4‑level data (passwords) not to appear in L3‑level logs.

Infrastructure/Hardware Vulnerabilities

Heartbleed – OpenSSL TLS implementation flaw.

Meltdown – CPU speculative‑execution vulnerability.

Log4j – Remote code execution via unfiltered JNDI lookups.

These flaws can lead to large‑scale credential theft.

How to Mitigate Password Insecurity

Absolute security is impossible; we aim for relative security. Password‑based authentication is inherently a trade‑off between security and convenience.

FIDO (Fast IDentity Online) proposes a password‑less approach. The WebAuthn API, defined by the FIDO Alliance and W3C, enables browsers to use asymmetric cryptography (e.g., fingerprint, facial recognition, USB security keys) instead of passwords, protecting against phishing and data leaks while improving user experience.

What Is WebAuthn?

WebAuthn (Web Authentication) is an API that replaces passwords or SMS codes with asymmetric‑key‑based authentication, providing resistance to phishing and data‑leak attacks.

WebAuthn works with biometrics (fingerprint, face) or hardware tokens (USB keys, Bluetooth devices).

Compatibility

Desktop browsers have good support; mobile support is limited (iOS ≥ 14.5, Android ≥ 5). WebAuthn requires HTTPS or localhost.

Key Concepts

User – the person authenticating.

User Agent – the browser or OS interacting with the authenticator.

Authenticator – device that replaces the password (fingerprint sensor, USB key, etc.).

Relying Party – the server that relies on the authentication.

Security Key – physical device (USB, NFC, Bluetooth).

FIDO – organization and protocol suite (UAF, U2F, FIDO2).

FIDO2 – core specifications WebAuthn (client) and CTAP (authenticator).

CTAP – Client‑to‑Authenticator Protocol (CTAP1/CTAP2).

Challenge – random string signed by the authenticator.

Attestation – data generated during registration.

Assertion – data generated during authentication.

Public Key Credential – the credential that replaces the password.

Workflow

Registration (Create)

Browser sends a registration request to the relying party.

Relying party returns a challenge, RP info, and user info.

Browser forwards a hash of the data to the authenticator.

Authenticator asks the user to verify (PIN, fingerprint) and creates a new key pair.

Authenticator returns the attestation object (public key, credential ID) to the browser.

Browser forwards the attestation to the relying party, which validates the challenge, origin, and signature, then stores the public key linked to the user.

Authentication (Get)

Relying party sends a challenge to the browser.

Browser forwards the challenge and RP ID to the authenticator.

Authenticator asks the user to verify and signs the challenge with the stored private key.

Authenticator returns the assertion (signed data) to the browser.

Browser forwards the assertion to the relying party.

Relying party verifies the signature with the stored public key; if valid, authentication succeeds.

Browser APIs

Registration: navigator.credentials.create(options)

Example options (simplified):

const options = {
  publicKey: {
    rp: { id: "example.com", name: "example.com" },
    user: { name: "[email protected]", id: userIdBuffer, displayName: "User Name" },
    pubKeyCredParams: [{ type: "public-key", alg: -7 }],
    challenge: challengeBuffer,
    authenticatorSelection: { authenticatorAttachment: "platform" }
  }
};

Key fields:

rp : relying party information.

user : user identifier (id must be a Uint8Array without personal data).

pubKeyCredParams : list of acceptable public‑key algorithms (e.g., ES256, RS256).

authenticatorSelection : preferences for platform vs. cross‑platform authenticators.

excludeCredentials : credentials that must not be reused.

Authentication: navigator.credentials.get(options)

Options are similar but include allowCredentials (list of credential IDs) and may set userVerification requirements.

const options = {
  publicKey: {
    challenge: challengeBuffer,
    rpId: "example.com",
    userVerification: "required",
    allowCredentials: []
  }
};

Discoverable Credentials (Password‑less Login)

When residentKey: "required" and userVerification: "required" are set, the authenticator stores the private key and user handle, allowing login without a username.

References

MDN: Web Authentication API – https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Authentication_API

W3C WebAuthn Spec – https://www.w3.org/TR/webauthn-3/

WebKit: Meet Face ID and Touch ID for the web – https://webkit.org/blog/11312/meet-face-id-and-touch-id-for-the-web/

Medium: Introduction to WebAuthn API – https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285

Various Chinese articles and guides (links omitted for brevity).

Authenticationhashingpassword securitysaltingcryptographyFIDOWebAuthn
ELab Team
Written by

ELab Team

Sharing fresh technical insights

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.