mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-08 10:27:41 +00:00
feat(crypto): support md5 plain for imported password hashes (#8189)
# Which Problems Are Solved Allow verification of imported passwords hashed with plain md5, without salt. These are password digests typically created by one of: - `printf "password" | md5sum` on most linux systems. - PHP's `md5("password")` - Python3's `hashlib.md5(b"password").hexdigest()` # How the Problems Are Solved - Upgrade passwap to [v0.6.0](https://github.com/zitadel/passwap/releases/tag/v0.6.0) - Add md5plain as a new verfier option in `defaults.yaml` # Additional Changes - Updated documentation to explain difference between `md5` (crypt) and `md5plain` verifiers. # Additional Context - Requested by customer for import case
This commit is contained in:
parent
bb609b642c
commit
dc170dc46e
@ -482,7 +482,8 @@ SystemDefaults:
|
|||||||
Verifiers: # ZITADEL_SYSTEMDEFAULTS_PASSWORDHASHER_VERIFIERS
|
Verifiers: # ZITADEL_SYSTEMDEFAULTS_PASSWORDHASHER_VERIFIERS
|
||||||
# - "argon2" # verifier for both argon2i and argon2id.
|
# - "argon2" # verifier for both argon2i and argon2id.
|
||||||
# - "bcrypt"
|
# - "bcrypt"
|
||||||
# - "md5"
|
# - "md5" # md5Crypt with salt and password shuffling.
|
||||||
|
# - "md5plain" # md5 digest of a password without salt
|
||||||
# - "scrypt"
|
# - "scrypt"
|
||||||
# - "pbkdf2" # verifier for all pbkdf2 hash modes.
|
# - "pbkdf2" # verifier for all pbkdf2 hash modes.
|
||||||
SecretHasher:
|
SecretHasher:
|
||||||
|
@ -68,7 +68,8 @@ The following hash algorithms are supported:
|
|||||||
|
|
||||||
- argon2i / id[^1]
|
- argon2i / id[^1]
|
||||||
- bcrypt (Default)
|
- bcrypt (Default)
|
||||||
- md5[^2]
|
- md5: implementation of md5Crypt with salt and password shuffling [^2]
|
||||||
|
- md5plain: md5 digest of a password without salt [^2]
|
||||||
- scrypt
|
- scrypt
|
||||||
- pbkdf2
|
- pbkdf2
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -59,7 +59,7 @@ require (
|
|||||||
github.com/ttacon/libphonenumber v1.2.1
|
github.com/ttacon/libphonenumber v1.2.1
|
||||||
github.com/zitadel/logging v0.6.0
|
github.com/zitadel/logging v0.6.0
|
||||||
github.com/zitadel/oidc/v3 v3.25.0
|
github.com/zitadel/oidc/v3 v3.25.0
|
||||||
github.com/zitadel/passwap v0.5.0
|
github.com/zitadel/passwap v0.6.0
|
||||||
github.com/zitadel/saml v0.1.3
|
github.com/zitadel/saml v0.1.3
|
||||||
github.com/zitadel/schema v1.3.0
|
github.com/zitadel/schema v1.3.0
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0
|
||||||
|
4
go.sum
4
go.sum
@ -731,8 +731,8 @@ github.com/zitadel/logging v0.6.0 h1:t5Nnt//r+m2ZhhoTmoPX+c96pbMarqJvW1Vq6xFTank
|
|||||||
github.com/zitadel/logging v0.6.0/go.mod h1:Y4CyAXHpl3Mig6JOszcV5Rqqsojj+3n7y2F591Mp/ow=
|
github.com/zitadel/logging v0.6.0/go.mod h1:Y4CyAXHpl3Mig6JOszcV5Rqqsojj+3n7y2F591Mp/ow=
|
||||||
github.com/zitadel/oidc/v3 v3.25.0 h1:DosOUc31IPM9ZtKaT58+0iNicwDFTFk5Ctt7mgYtsA8=
|
github.com/zitadel/oidc/v3 v3.25.0 h1:DosOUc31IPM9ZtKaT58+0iNicwDFTFk5Ctt7mgYtsA8=
|
||||||
github.com/zitadel/oidc/v3 v3.25.0/go.mod h1:UDwD+PRFbUBzabyPd9JORrakty3/wec7VpKZYi9Ahh0=
|
github.com/zitadel/oidc/v3 v3.25.0/go.mod h1:UDwD+PRFbUBzabyPd9JORrakty3/wec7VpKZYi9Ahh0=
|
||||||
github.com/zitadel/passwap v0.5.0 h1:kFMoRyo0GnxtOz7j9+r/CsRwSCjHGRaAKoUe69NwPvs=
|
github.com/zitadel/passwap v0.6.0 h1:m9F3epFC0VkBXu25rihSLGyHvWiNlCzU5kk8RoI+SXQ=
|
||||||
github.com/zitadel/passwap v0.5.0/go.mod h1:uqY7D3jqdTFcKsW0Q3Pcv5qDMmSHpVTzUZewUKC1KZA=
|
github.com/zitadel/passwap v0.6.0/go.mod h1:kqAiJ4I4eZvm3Y6oAk6hlEqlZZOkjMHraGXF90GG7LI=
|
||||||
github.com/zitadel/saml v0.1.3 h1:LI4DOCVyyU1qKPkzs3vrGcA5J3H4pH3+CL9zr9ShkpM=
|
github.com/zitadel/saml v0.1.3 h1:LI4DOCVyyU1qKPkzs3vrGcA5J3H4pH3+CL9zr9ShkpM=
|
||||||
github.com/zitadel/saml v0.1.3/go.mod h1:MdkjyU3mwnTuh4lNnhPG+RyZL/VfzD72wUG/eWWBaXc=
|
github.com/zitadel/saml v0.1.3/go.mod h1:MdkjyU3mwnTuh4lNnhPG+RyZL/VfzD72wUG/eWWBaXc=
|
||||||
github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0=
|
github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0=
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
@ -9,6 +11,7 @@ import (
|
|||||||
"github.com/zitadel/passwap/argon2"
|
"github.com/zitadel/passwap/argon2"
|
||||||
"github.com/zitadel/passwap/bcrypt"
|
"github.com/zitadel/passwap/bcrypt"
|
||||||
"github.com/zitadel/passwap/md5"
|
"github.com/zitadel/passwap/md5"
|
||||||
|
"github.com/zitadel/passwap/md5plain"
|
||||||
"github.com/zitadel/passwap/pbkdf2"
|
"github.com/zitadel/passwap/pbkdf2"
|
||||||
"github.com/zitadel/passwap/scrypt"
|
"github.com/zitadel/passwap/scrypt"
|
||||||
"github.com/zitadel/passwap/verifier"
|
"github.com/zitadel/passwap/verifier"
|
||||||
@ -19,6 +22,7 @@ import (
|
|||||||
type Hasher struct {
|
type Hasher struct {
|
||||||
*passwap.Swapper
|
*passwap.Swapper
|
||||||
Prefixes []string
|
Prefixes []string
|
||||||
|
HexSupported bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hasher) EncodingSupported(encodedHash string) bool {
|
func (h *Hasher) EncodingSupported(encodedHash string) bool {
|
||||||
@ -27,6 +31,12 @@ func (h *Hasher) EncodingSupported(encodedHash string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if h.HexSupported {
|
||||||
|
_, err := hex.DecodeString(encodedHash)
|
||||||
|
if err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +48,7 @@ const (
|
|||||||
HashNameArgon2id HashName = "argon2id" // hash only
|
HashNameArgon2id HashName = "argon2id" // hash only
|
||||||
HashNameBcrypt HashName = "bcrypt" // hash and verify
|
HashNameBcrypt HashName = "bcrypt" // hash and verify
|
||||||
HashNameMd5 HashName = "md5" // verify only, as hashing with md5 is insecure and deprecated
|
HashNameMd5 HashName = "md5" // verify only, as hashing with md5 is insecure and deprecated
|
||||||
|
HashNameMd5Plain HashName = "md5plain" // verify only, as hashing with md5 is insecure and deprecated
|
||||||
HashNameScrypt HashName = "scrypt" // hash and verify
|
HashNameScrypt HashName = "scrypt" // hash and verify
|
||||||
HashNamePBKDF2 HashName = "pbkdf2" // hash and verify
|
HashNamePBKDF2 HashName = "pbkdf2" // hash and verify
|
||||||
)
|
)
|
||||||
@ -71,6 +82,7 @@ func (c *HashConfig) NewHasher() (*Hasher, error) {
|
|||||||
return &Hasher{
|
return &Hasher{
|
||||||
Swapper: passwap.NewSwapper(hasher, verifiers...),
|
Swapper: passwap.NewSwapper(hasher, verifiers...),
|
||||||
Prefixes: append(hPrefixes, vPrefixes...),
|
Prefixes: append(hPrefixes, vPrefixes...),
|
||||||
|
HexSupported: slices.Contains(c.Verifiers, HashNameMd5Plain),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +107,10 @@ var knowVerifiers = map[HashName]prefixVerifier{
|
|||||||
prefixes: []string{md5.Prefix},
|
prefixes: []string{md5.Prefix},
|
||||||
verifier: md5.Verifier,
|
verifier: md5.Verifier,
|
||||||
},
|
},
|
||||||
|
HashNameMd5Plain: {
|
||||||
|
prefixes: nil, // hex encoded without identifier or prefix
|
||||||
|
verifier: md5plain.Verifier,
|
||||||
|
},
|
||||||
HashNameScrypt: {
|
HashNameScrypt: {
|
||||||
prefixes: []string{scrypt.Prefix, scrypt.Prefix_Linux},
|
prefixes: []string{scrypt.Prefix, scrypt.Prefix_Linux},
|
||||||
verifier: scrypt.Verifier,
|
verifier: scrypt.Verifier,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user