Skip to content

Add support for argon2#808

Open
Ph0tonic wants to merge 1 commit into
DirectoryTree:masterfrom
Ph0tonic:master
Open

Add support for argon2#808
Ph0tonic wants to merge 1 commit into
DirectoryTree:masterfrom
Ph0tonic:master

Conversation

@Ph0tonic

@Ph0tonic Ph0tonic commented Jun 9, 2026

Copy link
Copy Markdown

Hey, here is a PR to support argon hashing algorithm 🎉

Add argon2i and argon2id password hashing support

Adds Password::argon2i() and Password::argon2id() methods to the Password class, enabling use of the {ARGON2I} and {ARGON2ID} userPassword schemes supported by OpenLDAP via the pw-argon2 module.

Changes

  • Add Password::argon2i() and Password::argon2id() static methods using PHP's native password_hash()
  • Throw a LdapRecordException when attempting to change an argon2 password using the array syntax ($user->password = ['old', 'new']), since argon2 hashes are non-deterministic and the old hash cannot be reproduced to satisfy the LDAP REMOVE operation

Notes

  • Requires PHP 8.1+ (already the project minimum) with libargon2 support (standard on modern distributions)
  • Requires the OpenLDAP pw-argon2 contrib module to be loaded server-side (moduleload pw-argon2) — without it, the server will reject the {ARGON2ID} scheme
  • Password reset ($user->password = 'new') works as expected; only the password change (array) flow is unsupported — this can be addressed in a follow-up by implementing the LDAP Password Modify extended operation (ldap_exop_passwd)

@stevebauman

Copy link
Copy Markdown
Member

Thanks for the PR @Ph0tonic!

In regards to this:

Password reset ($user->password = 'new') works as expected; only the password change (array) flow is unsupported — this can be addressed in a follow-up by implementing the LDAP Password Modify extended operation (ldap_exop_passwd)

According to the docs for this method, it supports being called with $old_password here:

https://www.php.net/manual/en/function.ldap-exop-passwd.php

function ldap_exop_passwd(
    LDAP\Connection $ldap,
    string $user = "",
    #[\SensitiveParameter] string $old_password = "",
    #[\SensitiveParameter] string $new_password = "",
    array &$controls = null
): string|bool

So it looks like we may be able to support the same flow without throwing the exception here.

We could extract the mechanism for changing passwords into some interface and classes depending on the method being used. Maybe something like (psuedo-code):

$changer = match (strtolower($method)) {
    'argon2i', 'argon2id' => new ArgonPasswordChanger(...),
    default => new DefaultPasswordChanger(...),
};

Thoughts?

@stevebauman

stevebauman commented Jun 9, 2026

Copy link
Copy Markdown
Member

In other words I think we should implement the full operation here instead of in a follow up, because if the exception is no longer thrown then that's a major breaking change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants