diff --git a/hash/hash_comparator.go b/hash/hash_comparator.go index 4c6007ec94ff..160fab3d9d19 100644 --- a/hash/hash_comparator.go +++ b/hash/hash_comparator.go @@ -648,7 +648,20 @@ func decodeMD5Hash(encodedHash string) (pf, salt, hash []byte, err error) { switch len(parts) { case 3: hash, err := base64.StdEncoding.Strict().DecodeString(parts[2]) - return nil, nil, hash, err + if err != nil { + return nil, nil, nil, err + } + + // PHP's md5 function returns a hex encoded string instead of a raw hash by default (https://www.php.net/manual/en/function.md5.php). + passedHash, err := hex.DecodeString(string(hash)) + if err != nil { + // If the hash is not a hex encoded string. + // In this case we just return the base64 decoded hash. + return nil, nil, hash, nil + } + + // The hash is a hex encoded string, so we return the decoded hash. + return nil, nil, passedHash, nil case 5: _, err = fmt.Sscanf(parts[2], "pf=%s", &pf) if err != nil { diff --git a/hash/hasher_test.go b/hash/hasher_test.go index dc715d3d141f..ac47ce03b471 100644 --- a/hash/hasher_test.go +++ b/hash/hasher_test.go @@ -349,6 +349,9 @@ func TestCompare(t *testing.T) { assert.Nil(t, hash.CompareMD5(context.Background(), []byte("ory"), []byte("$md5$ptoWyof5SobW+pbZu2QXoQ=="))) assert.Error(t, hash.Compare(context.Background(), []byte("ory"), []byte("$md5$4skj967KRHFsnPFoL5dMMw=="))) + assert.Nil(t, hash.Compare(context.Background(), []byte("test"), []byte("$md5$MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY="))) + assert.Nil(t, hash.CompareMD5(context.Background(), []byte("test"), []byte("$md5$MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY="))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("ory"), []byte("$md5$$")), hash.ErrInvalidHash) assert.Error(t, hash.Compare(context.Background(), []byte("ory"), []byte("$md5$$$"))) assert.Error(t, hash.Compare(context.Background(), []byte("ory"), []byte("$md5$pf=$$")))