Rix is the official package layer for Vix.cpp Browse packages
Skip to content

Password Hash

This example shows how to hash and verify passwords with rix/auth.

The example uses the public Rix facade:

cpp
#include <rix.hpp>

and accesses password helpers through:

cpp
rix.auth.password

Use this example when you want to hash a plain-text password and verify login attempts safely.

Create the file

bash
mkdir -p ~/rix-auth-password-example
cd ~/rix-auth-password-example
touch password_hash.cpp

Add:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("== rix/auth password hashing ==");

  const auto password = "correct-password";

  auto hashed = rix.auth.password.hash(password);

  if (hashed.failed())
  {
    const auto &error = hashed.error();

    rix.debug.eprint(
        "auth error:",
        rix.auth.error.to_string(error),
        error.message());

    return 1;
  }

  const bool valid = rix.auth.password.verify(
      password,
      hashed.value());

  const bool invalid = rix.auth.password.verify(
      "wrong-password",
      hashed.value());

  rix.debug.print("hash:", hashed.value());
  rix.debug.print("valid password:", valid ? "yes" : "no");
  rix.debug.print("wrong password:", invalid ? "yes" : "no");

  if (!valid || invalid)
  {
    rix.debug.eprint("ERROR:", "password verification failed");
    return 1;
  }

  rix.debug.print("OK:", "password verification successful");
  return 0;
}

Run it:

bash
vix run password_hash.cpp

If Rix is not available yet for single-file usage:

bash
vix install -g rix/rix
vix run password_hash.cpp

Expected output shape:

txt
== rix/auth password hashing ==
hash: ...
valid password: yes
wrong password: no
OK: password verification successful

The exact hash value changes because password hashing uses a salt.

What this example does

The example defines a password:

cpp
const auto password = "correct-password";

It hashes the password:

cpp
auto hashed = rix.auth.password.hash(password);

It verifies the correct password:

cpp
const bool valid = rix.auth.password.verify(
    password,
    hashed.value());

It verifies that a wrong password does not match:

cpp
const bool invalid = rix.auth.password.verify(
    "wrong-password",
    hashed.value());

Hash a password

Use:

cpp
auto hashed = rix.auth.password.hash("correct-password");

hash returns a result.

Check it before using the stored hash:

cpp
if (hashed.failed())
{
  rix.debug.eprint(
      "auth error:",
      rix.auth.error.to_string(hashed.error()),
      hashed.error().message());

  return 1;
}

Then use:

cpp
hashed.value()

The value is an encoded password hash suitable for storage.

Do not store the plain-text password.

Verify a password

Use:

cpp
const bool ok = rix.auth.password.verify(
    "correct-password",
    hashed.value());

If the password matches the hash, the result is true.

If it does not match, the result is false.

cpp
if (ok)
{
  rix.debug.print("password accepted");
}

Wrong password check

A wrong password should fail:

cpp
const bool wrong = rix.auth.password.verify(
    "wrong-password",
    hashed.value());

if (!wrong)
{
  rix.debug.print("wrong password rejected");
}

This is the expected behavior.

Result pattern

hash returns an auth result.

Use:

cpp
hashed.ok()
hashed.failed()
hashed.value()
hashed.error()

Never call value() before checking success.

Wrong:

cpp
auto hashed = rix.auth.password.hash("correct-password");

rix.debug.print(hashed.value());

Correct:

cpp
auto hashed = rix.auth.password.hash("correct-password");

if (hashed.failed())
{
  return 1;
}

rix.debug.print(hashed.value());

Password policy

Password hashing checks the configured password policy.

By default, the development configuration accepts passwords with a minimum length suitable for examples and local development.

This can fail:

cpp
auto hashed = rix.auth.password.hash("short");

Handle the error:

cpp
if (hashed.failed())
{
  rix.debug.eprint(
      "auth error:",
      rix.auth.error.to_string(hashed.error()),
      hashed.error().message());
}

Check whether a password is accepted

Use:

cpp
const bool accepted = rix.auth.password.accepts("correct-password");

Example:

cpp
if (!rix.auth.password.accepts("short"))
{
  rix.debug.eprint("password rejected by policy");
}

accepts checks the length policy.

hash also checks the policy before creating a hash.

Use a custom configuration

You can hash and verify with a custom auth configuration.

cpp
auto config = rix.auth.config.development();

config.set_min_password_length(8);
config.set_password_hash_iterations(310000);
config.set_password_salt_size(16);
config.set_password_hash_size(32);

auto hashed = rix.auth.password.hash(
    "correct-password",
    config);

Verify with the same style:

cpp
const bool ok = rix.auth.password.verify(
    "correct-password",
    hashed.value(),
    config);

Use custom configuration when your application needs stricter or different password policy settings.

Create a hasher

You can create a password hasher through the facade:

cpp
auto hasher = rix.auth.password.hasher();

Then:

cpp
auto hashed = hasher.hash("correct-password");

const bool ok = hasher.verify(
    "correct-password",
    hashed.value());

With configuration:

cpp
auto config = rix.auth.config.production();

auto hasher = rix.auth.password.hasher(config);

For most examples, the facade helpers are enough:

cpp
rix.auth.password.hash(...)
rix.auth.password.verify(...)

Complete custom policy example

cpp
#include <rix.hpp>

int main()
{
  auto config = rix.auth.config.development();

  config.set_min_password_length(12);

  const auto password = "correct-password";

  auto hashed = rix.auth.password.hash(
      password,
      config);

  if (hashed.failed())
  {
    rix.debug.eprint(
        "auth error:",
        rix.auth.error.to_string(hashed.error()),
        hashed.error().message());

    return 1;
  }

  const bool ok = rix.auth.password.verify(
      password,
      hashed.value(),
      config);

  rix.debug.print("password valid:", ok ? "yes" : "no");

  return ok ? 0 : 1;
}

Run:

bash
vix run password_hash.cpp

Use with registration

Normally, you do not need to call password hashing directly during registration.

auth.register_user hashes the password internally.

cpp
auto auth = rix.auth.memory();

auto registered = auth.register_user({
    "ada@example.com",
    "correct-password"});

Use rix.auth.password.hash directly when you are writing lower-level auth utilities, tests, import tools, adapters, or custom flows.

Use with login

Normally, you do not need to call password verification directly during login.

auth.login verifies the password internally.

cpp
auto login = auth.login({
    "ada@example.com",
    "correct-password"});

Use rix.auth.password.verify directly when testing, migrating stored hashes, or building custom auth flows.

Safe output

Do not print plain-text passwords.

Do not print password hashes in production logs.

This example prints the hash only to show that a hash was produced.

For real applications, store the hash and keep logs clean.

Use in a Vix project

Create a project:

bash
vix new rix-auth-password --app
cd rix-auth-password

Add Rix:

bash
vix add rix/rix
vix install

Make sure vix.app contains:

txt
deps = [
  "rix/rix",
]

A minimal vix.app can look like this:

txt
name = "rix-auth-password"
type = "executable"
standard = "c++20"
output_dir = "bin"

sources = [
  "src/main.cpp",
]

include_dirs = [
  "include",
  "src",
]

deps = [
  "rix/rix",
]

packages = [
  "vix",
]

links = [
  "vix::vix",
]

Put the example code in:

txt
src/main.cpp

Build and run:

bash
vix build
vix run

Single-file usage

For examples, tests, and quick experiments:

bash
vix run password_hash.cpp

If needed:

bash
vix install -g rix/rix
vix run password_hash.cpp

For project usage, prefer:

bash
vix add rix/rix
vix install

and keep the dependency in vix.app:

txt
deps = [
  "rix/rix",
]

Use only auth with the facade

If you want the rix.* facade style but only want auth mounted, define the feature macro before including rix.hpp:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

int main()
{
  auto hashed = rix.auth.password.hash("correct-password");

  return hashed.ok() ? 0 : 1;
}

When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.

If you also want debug output:

cpp
#define RIX_ENABLE_AUTH
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  auto hashed = rix.auth.password.hash("correct-password");

  if (hashed.failed())
  {
    rix.debug.eprint(
        "auth error:",
        rix.auth.error.to_string(hashed.error()),
        hashed.error().message());

    return 1;
  }

  rix.debug.print("hash created");
  return 0;
}

Use the independent package

For independent usage, install:

bash
vix add rix/auth
vix install

In vix.app:

txt
deps = [
  "rix/auth",
]

Then include auth package headers directly.

The examples in this documentation prefer the public facade:

cpp
#include <rix.hpp>

and:

cpp
rix.auth

Common mistakes

Forgetting to install Rix

If rix.hpp is not found, install Rix first.

For a project:

bash
vix add rix/rix
vix install

For single-file usage:

bash
vix install -g rix/rix

Putting Rix in packages

Wrong:

txt
packages = [
  "rix/rix",
]

Correct:

txt
deps = [
  "rix/rix",
]

deps is for Vix Registry packages.

packages is for CMake package discovery.

Calling value() before checking success

Wrong:

cpp
auto hashed = rix.auth.password.hash("correct-password");

const auto &stored_hash = hashed.value();

Correct:

cpp
auto hashed = rix.auth.password.hash("correct-password");

if (hashed.failed())
{
  return 1;
}

const auto &stored_hash = hashed.value();

Expecting the same hash every time

Password hashes include a salt.

This means hashing the same password twice can produce different encoded hashes.

That is expected.

Use verify to check whether a password matches a stored hash.

Logging passwords

Never log:

txt
plain-text passwords
password hashes in production

For docs, the hash may be printed to show the example result.

For production, do not print it.

Verifying against an empty hash

This returns false:

cpp
rix.auth.password.verify(
    "correct-password",
    "");

Always store and pass the encoded hash returned by hash.

What you should remember

Hash a password:

cpp
auto hashed = rix.auth.password.hash("correct-password");

Check the result:

cpp
if (hashed.failed())
{
  rix.debug.eprint(
      "auth error:",
      rix.auth.error.to_string(hashed.error()),
      hashed.error().message());

  return 1;
}

Verify the password:

cpp
const bool ok = rix.auth.password.verify(
    "correct-password",
    hashed.value());

Wrong passwords return false:

cpp
const bool wrong = rix.auth.password.verify(
    "wrong-password",
    hashed.value());

For project usage:

bash
vix add rix/rix
vix install

and keep:

txt
deps = [
  "rix/rix",
]

Next step

Continue with session refresh and logout.

Next: Session refresh and logout

Released under the MIT License.