mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:37:32 +00:00
feat(crypto): support md5 salted for imported password hashes (#9596)
# Which Problems Are Solved Allow verification of imported salted passwords hashed with plain md5. # How the Problems Are Solved - Upgrade passwap to [v0.7.0](https://github.com/zitadel/passwap/releases/tag/v0.7.0) - Add md5salted as a new verifier option in `defaults.yaml` # Additional Changes - go version and libraries updated (required by passkey v0.7.0) - secrets.md verifiers updated - configuration verifiers updated - added MD5salted and missing MD5Plain to test cases
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/zitadel/passwap/bcrypt"
|
||||
"github.com/zitadel/passwap/md5"
|
||||
"github.com/zitadel/passwap/md5plain"
|
||||
"github.com/zitadel/passwap/md5salted"
|
||||
"github.com/zitadel/passwap/pbkdf2"
|
||||
"github.com/zitadel/passwap/scrypt"
|
||||
"github.com/zitadel/passwap/verifier"
|
||||
@@ -43,14 +44,15 @@ func (h *Hasher) EncodingSupported(encodedHash string) bool {
|
||||
type HashName string
|
||||
|
||||
const (
|
||||
HashNameArgon2 HashName = "argon2" // used for the common argon2 verifier
|
||||
HashNameArgon2i HashName = "argon2i" // hash only
|
||||
HashNameArgon2id HashName = "argon2id" // hash only
|
||||
HashNameBcrypt HashName = "bcrypt" // hash and verify
|
||||
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
|
||||
HashNamePBKDF2 HashName = "pbkdf2" // hash and verify
|
||||
HashNameArgon2 HashName = "argon2" // used for the common argon2 verifier
|
||||
HashNameArgon2i HashName = "argon2i" // hash only
|
||||
HashNameArgon2id HashName = "argon2id" // hash only
|
||||
HashNameBcrypt HashName = "bcrypt" // hash and verify
|
||||
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
|
||||
HashNameMd5Salted HashName = "md5salted" // verify only, as hashing with md5 is insecure and deprecated
|
||||
HashNameScrypt HashName = "scrypt" // hash and verify
|
||||
HashNamePBKDF2 HashName = "pbkdf2" // hash and verify
|
||||
)
|
||||
|
||||
type HashMode string
|
||||
@@ -119,6 +121,10 @@ var knowVerifiers = map[HashName]prefixVerifier{
|
||||
prefixes: []string{pbkdf2.Prefix},
|
||||
verifier: pbkdf2.Verifier,
|
||||
},
|
||||
HashNameMd5Salted: {
|
||||
prefixes: []string{md5salted.Prefix},
|
||||
verifier: md5salted.Verifier,
|
||||
},
|
||||
}
|
||||
|
||||
func (c *HashConfig) buildVerifiers() (verifiers []verifier.Verifier, prefixes []string, err error) {
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/zitadel/passwap/argon2"
|
||||
"github.com/zitadel/passwap/bcrypt"
|
||||
"github.com/zitadel/passwap/md5"
|
||||
"github.com/zitadel/passwap/md5salted"
|
||||
"github.com/zitadel/passwap/pbkdf2"
|
||||
"github.com/zitadel/passwap/scrypt"
|
||||
)
|
||||
@@ -76,6 +77,7 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
HashNameArgon2,
|
||||
HashNameBcrypt,
|
||||
HashNameMd5,
|
||||
HashNameMd5Salted,
|
||||
HashNameScrypt,
|
||||
"foobar",
|
||||
},
|
||||
@@ -122,6 +124,24 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid md5plain",
|
||||
fields: fields{
|
||||
Hasher: HasherConfig{
|
||||
Algorithm: HashNameMd5Plain,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid md5salted",
|
||||
fields: fields{
|
||||
Hasher: HasherConfig{
|
||||
Algorithm: HashNameMd5Salted,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid argon2",
|
||||
fields: fields{
|
||||
@@ -160,9 +180,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"threads": 4,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameBcrypt, HashNameMd5, HashNameScrypt},
|
||||
Verifiers: []HashName{HashNameBcrypt, HashNameMd5, HashNameScrypt, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{argon2.Prefix, bcrypt.Prefix, md5.Prefix, scrypt.Prefix, scrypt.Prefix_Linux},
|
||||
wantPrefixes: []string{argon2.Prefix, bcrypt.Prefix, md5.Prefix, scrypt.Prefix, scrypt.Prefix_Linux, md5salted.Prefix},
|
||||
},
|
||||
{
|
||||
name: "argon2id, error",
|
||||
@@ -188,9 +208,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"threads": 4,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameBcrypt, HashNameMd5, HashNameScrypt},
|
||||
Verifiers: []HashName{HashNameBcrypt, HashNameMd5, HashNameScrypt, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{argon2.Prefix, bcrypt.Prefix, md5.Prefix, scrypt.Prefix, scrypt.Prefix_Linux},
|
||||
wantPrefixes: []string{argon2.Prefix, bcrypt.Prefix, md5.Prefix, scrypt.Prefix, scrypt.Prefix_Linux, md5salted.Prefix},
|
||||
},
|
||||
{
|
||||
name: "bcrypt, error",
|
||||
@@ -213,9 +233,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"cost": 3,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameMd5, HashNameScrypt},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameMd5, HashNameScrypt, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{bcrypt.Prefix, argon2.Prefix, md5.Prefix, scrypt.Prefix, scrypt.Prefix_Linux},
|
||||
wantPrefixes: []string{bcrypt.Prefix, argon2.Prefix, md5.Prefix, scrypt.Prefix, scrypt.Prefix_Linux, md5salted.Prefix},
|
||||
},
|
||||
{
|
||||
name: "scrypt, error",
|
||||
@@ -238,9 +258,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"cost": 3,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{scrypt.Prefix, scrypt.Prefix_Linux, argon2.Prefix, bcrypt.Prefix, md5.Prefix},
|
||||
wantPrefixes: []string{scrypt.Prefix, scrypt.Prefix_Linux, argon2.Prefix, bcrypt.Prefix, md5.Prefix, md5salted.Prefix},
|
||||
},
|
||||
{
|
||||
name: "pbkdf2, parse error",
|
||||
@@ -277,9 +297,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"Hash": HashModeSHA1,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix, md5salted.Prefix},
|
||||
},
|
||||
{
|
||||
name: "pbkdf2, sha224",
|
||||
@@ -291,9 +311,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"Hash": HashModeSHA224,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix, md5salted.Prefix},
|
||||
},
|
||||
{
|
||||
name: "pbkdf2, sha256",
|
||||
@@ -305,9 +325,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"Hash": HashModeSHA256,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix, md5salted.Prefix},
|
||||
},
|
||||
{
|
||||
name: "pbkdf2, sha384",
|
||||
@@ -319,9 +339,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"Hash": HashModeSHA384,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix, md5salted.Prefix},
|
||||
},
|
||||
{
|
||||
name: "pbkdf2, sha512",
|
||||
@@ -333,9 +353,9 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
"Hash": HashModeSHA512,
|
||||
},
|
||||
},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5},
|
||||
Verifiers: []HashName{HashNameArgon2, HashNameBcrypt, HashNameMd5, HashNameMd5Plain, HashNameMd5Salted},
|
||||
},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix},
|
||||
wantPrefixes: []string{pbkdf2.Prefix, argon2.Prefix, bcrypt.Prefix, md5.Prefix, md5salted.Prefix},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
Reference in New Issue
Block a user