feat(api): integrates drupal7 hash verifier from passwap (#10918)

# Which Problems Are Solved

- Integrates the Drupal 7 hash verifier from passwap

# Additional Changes

- The docs inform about the option to use the Drupal 7 hash verifier
- Updates passwap to version v0.10.0

# Additional Context

- Follow-up for PR
[#passwap/pull/70](https://github.com/zitadel/passwap/pull/70)

Co-authored-by: Marco A. <marco@zitadel.com>
This commit is contained in:
lennartzellmer
2025-10-28 17:26:48 +01:00
committed by GitHub
parent 39a29f534a
commit f4503e07cd
3 changed files with 23 additions and 2 deletions

View File

@@ -72,12 +72,13 @@ The following hash algorithms are supported:
- md5plain: md5 digest of a password without salt [^2] - md5plain: md5 digest of a password without salt [^2]
- md5salted: md5 digest of a salted password [^2] - md5salted: md5 digest of a salted password [^2]
- phpass: md5 digest with PHPass algorithm (used in WordPress) [^2] - phpass: md5 digest with PHPass algorithm (used in WordPress) [^2]
- drupal7: Custom hashing format used in Drupal 7 [^2]
- sha2: implementation of crypt(3) SHA-256 & SHA-512 - sha2: implementation of crypt(3) SHA-256 & SHA-512
- scrypt - scrypt
- pbkdf2 - pbkdf2
[^1]: argon2 algorithms are currently disabled on ZITADEL Cloud due to its steep memory requirements. [^1]: argon2 algorithms are currently disabled on ZITADEL Cloud due to its steep memory requirements.
[^2]: md5 is insecure and can only be used to import and verify users, not hash new passwords. [^2]: md5 and drupal7 are insecure and can only be used to import and verify users, not hash new passwords.
:::info :::info
ZITADEL updates stored hashes when the configured algorithm or its parameters are updated, ZITADEL updates stored hashes when the configured algorithm or its parameters are updated,

View File

@@ -10,6 +10,7 @@ import (
"github.com/zitadel/passwap" "github.com/zitadel/passwap"
"github.com/zitadel/passwap/argon2" "github.com/zitadel/passwap/argon2"
"github.com/zitadel/passwap/bcrypt" "github.com/zitadel/passwap/bcrypt"
"github.com/zitadel/passwap/drupal7"
"github.com/zitadel/passwap/md5" "github.com/zitadel/passwap/md5"
"github.com/zitadel/passwap/md5plain" "github.com/zitadel/passwap/md5plain"
"github.com/zitadel/passwap/md5salted" "github.com/zitadel/passwap/md5salted"
@@ -57,6 +58,7 @@ const (
HashNameSha2 HashName = "sha2" // hash and verify HashNameSha2 HashName = "sha2" // hash and verify
HashNameScrypt HashName = "scrypt" // hash and verify HashNameScrypt HashName = "scrypt" // hash and verify
HashNamePBKDF2 HashName = "pbkdf2" // hash and verify HashNamePBKDF2 HashName = "pbkdf2" // hash and verify
HashNameDrupal7 HashName = "drupal7" // verify only, Drupal 7 legacy hashes
) )
type HashMode string type HashMode string
@@ -137,6 +139,10 @@ var knowVerifiers = map[HashName]prefixVerifier{
prefixes: []string{phpass.IdentifierP, phpass.IdentifierH}, prefixes: []string{phpass.IdentifierP, phpass.IdentifierH},
verifier: phpass.Verifier, verifier: phpass.Verifier,
}, },
HashNameDrupal7: {
prefixes: []string{drupal7.Identifier},
verifier: drupal7.Verifier,
},
} }
func (c *HashConfig) buildVerifiers() (verifiers []verifier.Verifier, prefixes []string, err error) { func (c *HashConfig) buildVerifiers() (verifiers []verifier.Verifier, prefixes []string, err error) {
@@ -174,7 +180,7 @@ func (c *HasherConfig) buildHasher() (hasher passwap.Hasher, prefixes []string,
return c.sha2() return c.sha2()
case "": case "":
return nil, nil, fmt.Errorf("missing hasher algorithm") return nil, nil, fmt.Errorf("missing hasher algorithm")
case HashNameArgon2, HashNameMd5, HashNameMd5Plain, HashNameMd5Salted, HashNamePHPass: case HashNameArgon2, HashNameMd5, HashNameMd5Plain, HashNameMd5Salted, HashNamePHPass, HashNameDrupal7:
fallthrough fallthrough
default: default:
return nil, nil, fmt.Errorf("invalid algorithm %q", c.Algorithm) return nil, nil, fmt.Errorf("invalid algorithm %q", c.Algorithm)

View File

@@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/zitadel/passwap/argon2" "github.com/zitadel/passwap/argon2"
"github.com/zitadel/passwap/bcrypt" "github.com/zitadel/passwap/bcrypt"
"github.com/zitadel/passwap/drupal7"
"github.com/zitadel/passwap/md5" "github.com/zitadel/passwap/md5"
"github.com/zitadel/passwap/md5salted" "github.com/zitadel/passwap/md5salted"
"github.com/zitadel/passwap/pbkdf2" "github.com/zitadel/passwap/pbkdf2"
@@ -249,6 +250,19 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
}, },
wantPrefixes: []string{bcrypt.Prefix, argon2.Prefix, md5.Prefix, scrypt.Prefix, scrypt.Prefix_Linux, md5salted.Prefix}, wantPrefixes: []string{bcrypt.Prefix, argon2.Prefix, md5.Prefix, scrypt.Prefix, scrypt.Prefix_Linux, md5salted.Prefix},
}, },
{
name: "drupal7 verifier",
fields: fields{
Hasher: HasherConfig{
Algorithm: HashNameBcrypt,
Params: map[string]any{
"cost": 3,
},
},
Verifiers: []HashName{HashNameDrupal7},
},
wantPrefixes: []string{bcrypt.Prefix, drupal7.Identifier},
},
{ {
name: "scrypt, error", name: "scrypt, error",
fields: fields{ fields: fields{