diff --git a/hash/hash_comparator.go b/hash/hash_comparator.go index f3169f6f5ea3..916585f3a1fd 100644 --- a/hash/hash_comparator.go +++ b/hash/hash_comparator.go @@ -14,7 +14,9 @@ import ( "crypto/subtle" "encoding/base64" "fmt" + "hash" "regexp" + "strconv" "strings" "github.com/pkg/errors" @@ -48,6 +50,8 @@ func Compare(ctx context.Context, password []byte, hash []byte) error { return CompareFirebaseScrypt(ctx, password, hash) case IsMD5Hash(hash): return CompareMD5(ctx, password, hash) + case IsLegacyHash(hash): + return CompareLegacy(ctx, password, hash) default: return errors.WithStack(ErrUnknownHashAlgorithm) } @@ -232,6 +236,18 @@ func CompareMD5(_ context.Context, password []byte, hash []byte) error { return errors.WithStack(ErrMismatchedHashAndPassword) } +func CompareLegacy(ctx context.Context, pwd, encodedHash []byte) error { + phc, alg, format, iterations, salt, pepper, err := decodeLegacyHash(string(encodedHash)) + if err != nil { + return err + } + hash, err := legacyHash(alg, format, iterations, salt, pepper, pwd) + if err != nil { + return err + } + return CompareArgon2id(ctx, hash, []byte(phc)) +} + var ( isBcryptHash = regexp.MustCompile(`^\$2[abzy]?\$`) isArgon2idHash = regexp.MustCompile(`^\$argon2id\$`) @@ -242,6 +258,7 @@ var ( isSHAHash = regexp.MustCompile(`^\$sha(1|256|512)\$`) isFirebaseScryptHash = regexp.MustCompile(`^\$firescrypt\$`) isMD5Hash = regexp.MustCompile(`^\$md5\$`) + isLegacyHash = regexp.MustCompile(`^\$legacy\$`) ) func IsBcryptHash(hash []byte) bool { return isBcryptHash.Match(hash) } @@ -253,6 +270,7 @@ func IsSSHAHash(hash []byte) bool { return isSSHAHash.Match(hash) } func IsSHAHash(hash []byte) bool { return isSHAHash.Match(hash) } func IsFirebaseScryptHash(hash []byte) bool { return isFirebaseScryptHash.Match(hash) } func IsMD5Hash(hash []byte) bool { return isMD5Hash.Match(hash) } +func IsLegacyHash(hash []byte) bool { return isLegacyHash.Match(hash) } func IsValidHashFormat(hash []byte) bool { if IsBcryptHash(hash) || @@ -263,7 +281,8 @@ func IsValidHashFormat(hash []byte) bool { IsSSHAHash(hash) || IsSHAHash(hash) || IsFirebaseScryptHash(hash) || - IsMD5Hash(hash) { + IsMD5Hash(hash) || + IsLegacyHash(hash) { return true } else { return false @@ -558,3 +577,80 @@ func decodeMD5Hash(encodedHash string) (pf, salt, hash []byte, err error) { return nil, nil, nil, ErrInvalidHash } } + +// decodeLegacyHash decodes argon2id wrapped legacy password hash. +// format: $legacy$alg=,format=,i=,(salt=,pepper=)$ +func decodeLegacyHash(encodedHash string) (phc, alg, format string, iterations int, salt, pepper []byte, err error) { + parts := strings.SplitN(encodedHash, "$", 4) + if len(parts) != 4 { + return "", "", "", 0, nil, nil, ErrInvalidHash + } + phc = "$" + parts[3] + legacyParams := strings.Split(parts[2], ",") + for _, lp := range legacyParams { + k, v, found := strings.Cut(lp, "=") + if !found { + return "", "", "", 0, nil, nil, ErrInvalidHash + } + switch k { + case "alg": + alg = v + case "format": + f, err := base64.RawStdEncoding.DecodeString(v) + if err != nil { + return "", "", "", 0, nil, nil, ErrInvalidHash + } + format = string(f) + case "i": + iterations, err = strconv.Atoi(v) + if err != nil { + return "", "", "", 0, nil, nil, ErrInvalidHash + } + case "salt": + salt, err = base64.RawStdEncoding.DecodeString(v) + if err != nil { + return "", "", "", 0, nil, nil, ErrInvalidHash + } + case "pepper": + pepper, err = base64.RawStdEncoding.DecodeString(v) + if err != nil { + return "", "", "", 0, nil, nil, ErrInvalidHash + } + } + } + return +} + +func legacyHash(alg, format string, iterations int, salt, pepper, pwd []byte) ([]byte, error) { + if len(pwd) < 1 || !strings.Contains(format, "{PWD}") || iterations < 1 || !(alg == "md5" || alg == "sha1" || alg == "sha256" || alg == "sha512") { + return nil, ErrInvalidHash + } + replacements := []string{"{PWD}", string(pwd)} + if salt != nil { + replacements = append(replacements, "{SALT}", string(salt)) + } + if pepper != nil { + replacements = append(replacements, "{PEPPER}", string(pepper)) + } + toHash := []byte(strings.NewReplacer(replacements...).Replace(format)) + + var hasher hash.Hash + switch alg { + case "md5": + hasher = md5.New() //#nosec G401 -- compatibility for imported passwords + case "sha1": + hasher = sha1.New() //#nosec G401 -- compatibility for imported passwords + case "sha256": + hasher = sha256.New() + case "sha512": + hasher = sha512.New() + default: + return nil, ErrUnknownHashAlgorithm + } + for i := 1; i <= iterations; i++ { + hasher.Write(toHash) + toHash = hasher.Sum([]byte{}) + hasher.Reset() + } + return toHash, nil +} diff --git a/hash/hasher_test.go b/hash/hasher_test.go index 030898ce63d6..081ec4bf2beb 100644 --- a/hash/hasher_test.go +++ b/hash/hasher_test.go @@ -365,4 +365,105 @@ func TestCompare(t *testing.T) { assert.Nil(t, hash.CompareMD5(context.Background(), []byte("ory"), []byte("$md5$pf=e1BBU1NXT1JEfXtTQUxUfSQ/$MTIzNDU2Nzg5$8PhwWanVRnpJAFK4NUjR0w=="))) // pf={PASSWORD}{SALT}$? salt=123456789 assert.Error(t, hash.CompareMD5(context.Background(), []byte("ory1"), []byte("$md5$pf=e1BBU1NXT1JEfXtTQUxUfSQ/$MTIzNDU2Nzg5$8PhwWanVRnpJAFK4NUjR0w=="))) }) + + t.Run("legacy", func(t *testing.T) { + t.Parallel() + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=md5,format=e1NBTFR9Ojp7UFdEfTo6e1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$YuYcJII0fm8UXm8XiCqimA$xzUihMR5G40U3Gf2CmTfNhXDYTtva6ykbjGnfQnWCac"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=md5,format=e1NBTFR9Ojp7UFdEfTo6e1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$YuYcJII0fm8UXm8XiCqimA$xzUihMR5G40U3Gf2CmTfNhXDYTtva6ykbjGnfQnWCac"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=md5,format=e1NBTFR9Ojp7UFdEfTo6e1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$YuYcJII0fm8UXm8XiCqimA$xzUihMR5G40U3Gf2CmTfNhXDYTtva6ykbjGnfQnWCac")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=md5,format=e1NBTFR9Ojp7UFdEfTo6e1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$YuYcJII0fm8UXm8XiCqimA$xzUihMR5G40U3Gf2CmTfNhXDYTtva6ykbjGnfQnWCac")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=md5,format=e1BFUFBFUn0te1BXRH0te1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$Ga8HwG3MBtzAOIBy5JIOBg$MhUzhn2rkyOqRFmbSQ3pXB59qKW+IIg7yJdKAcsBiME"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=md5,format=e1BFUFBFUn0te1BXRH0te1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$Ga8HwG3MBtzAOIBy5JIOBg$MhUzhn2rkyOqRFmbSQ3pXB59qKW+IIg7yJdKAcsBiME"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=md5,format=e1BFUFBFUn0te1BXRH0te1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$Ga8HwG3MBtzAOIBy5JIOBg$MhUzhn2rkyOqRFmbSQ3pXB59qKW+IIg7yJdKAcsBiME")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=md5,format=e1BFUFBFUn0te1BXRH0te1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$Ga8HwG3MBtzAOIBy5JIOBg$MhUzhn2rkyOqRFmbSQ3pXB59qKW+IIg7yJdKAcsBiME")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=md5,format=e1NBTFR9e1BXRH0,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$zyb+7mv9xiiCpYBepfJqeg$tjqa+jQkCSJLHjWxBKbMHwXB60ZDigMh8qfm1+EdKBk"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=md5,format=e1NBTFR9e1BXRH0,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$zyb+7mv9xiiCpYBepfJqeg$tjqa+jQkCSJLHjWxBKbMHwXB60ZDigMh8qfm1+EdKBk"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=md5,format=e1NBTFR9e1BXRH0,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$zyb+7mv9xiiCpYBepfJqeg$tjqa+jQkCSJLHjWxBKbMHwXB60ZDigMh8qfm1+EdKBk")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=md5,format=e1NBTFR9e1BXRH0,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$zyb+7mv9xiiCpYBepfJqeg$tjqa+jQkCSJLHjWxBKbMHwXB60ZDigMh8qfm1+EdKBk")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=md5,format=e1BXRH0ve1BFUFBFUn0,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$I4dIAHH3rh+0W8KTiZjnCg$yd2Ctn5GEwAx9wl9UA6eIBUcSxUoVK7AQMDu6oDFLzc"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=md5,format=e1BXRH0ve1BFUFBFUn0,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$I4dIAHH3rh+0W8KTiZjnCg$yd2Ctn5GEwAx9wl9UA6eIBUcSxUoVK7AQMDu6oDFLzc"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=md5,format=e1BXRH0ve1BFUFBFUn0,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$I4dIAHH3rh+0W8KTiZjnCg$yd2Ctn5GEwAx9wl9UA6eIBUcSxUoVK7AQMDu6oDFLzc")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=md5,format=e1BXRH0ve1BFUFBFUn0,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$I4dIAHH3rh+0W8KTiZjnCg$yd2Ctn5GEwAx9wl9UA6eIBUcSxUoVK7AQMDu6oDFLzc")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha1,format=e1NBTFR9Pz97UFdEfSEhe1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$SpCzXlHnPS+dQNvNnkuc0A$AHm9Xxapstu2cJLQ0CUVRbJBvJ+rdHavqZi+1RB0nWg"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha1,format=e1NBTFR9Pz97UFdEfSEhe1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$SpCzXlHnPS+dQNvNnkuc0A$AHm9Xxapstu2cJLQ0CUVRbJBvJ+rdHavqZi+1RB0nWg"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha1,format=e1NBTFR9Pz97UFdEfSEhe1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$SpCzXlHnPS+dQNvNnkuc0A$AHm9Xxapstu2cJLQ0CUVRbJBvJ+rdHavqZi+1RB0nWg")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha1,format=e1NBTFR9Pz97UFdEfSEhe1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$SpCzXlHnPS+dQNvNnkuc0A$AHm9Xxapstu2cJLQ0CUVRbJBvJ+rdHavqZi+1RB0nWg")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha1,format=e1BFUFBFUn17UFdEfS4ue1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ljo67QnINSCNCtVone0A3A$muO63T/xcwNZbzXp0dkPL4T5e+j6gdOj+okpQEx802c"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha1,format=e1BFUFBFUn17UFdEfS4ue1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ljo67QnINSCNCtVone0A3A$muO63T/xcwNZbzXp0dkPL4T5e+j6gdOj+okpQEx802c"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha1,format=e1BFUFBFUn17UFdEfS4ue1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ljo67QnINSCNCtVone0A3A$muO63T/xcwNZbzXp0dkPL4T5e+j6gdOj+okpQEx802c")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha1,format=e1BFUFBFUn17UFdEfS4ue1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ljo67QnINSCNCtVone0A3A$muO63T/xcwNZbzXp0dkPL4T5e+j6gdOj+okpQEx802c")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha1,format=LXtTQUxUfXtQV0R9LQ,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$1PDgq4Oh5NCQ3+3O0qdqbw$l7Ed+ifHZS5Hj4EJnSHdXpeCAJHgl8ns6FlpywrlGDU"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha1,format=LXtTQUxUfXtQV0R9LQ,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$1PDgq4Oh5NCQ3+3O0qdqbw$l7Ed+ifHZS5Hj4EJnSHdXpeCAJHgl8ns6FlpywrlGDU"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha1,format=LXtTQUxUfXtQV0R9LQ,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$1PDgq4Oh5NCQ3+3O0qdqbw$l7Ed+ifHZS5Hj4EJnSHdXpeCAJHgl8ns6FlpywrlGDU")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha1,format=LXtTQUxUfXtQV0R9LQ,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$1PDgq4Oh5NCQ3+3O0qdqbw$l7Ed+ifHZS5Hj4EJnSHdXpeCAJHgl8ns6FlpywrlGDU")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha1,format=e1BXRH0le1BFUFBFUn0l,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$b89HPDYNAoRS4XEp0WZkug$BOQ/jxQ6oqbWXwGn3KV1uybbZkkMkS1R1bFuObgZqDY"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha1,format=e1BXRH0le1BFUFBFUn0l,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$b89HPDYNAoRS4XEp0WZkug$BOQ/jxQ6oqbWXwGn3KV1uybbZkkMkS1R1bFuObgZqDY"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha1,format=e1BXRH0le1BFUFBFUn0l,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$b89HPDYNAoRS4XEp0WZkug$BOQ/jxQ6oqbWXwGn3KV1uybbZkkMkS1R1bFuObgZqDY")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha1,format=e1BXRH0le1BFUFBFUn0l,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$b89HPDYNAoRS4XEp0WZkug$BOQ/jxQ6oqbWXwGn3KV1uybbZkkMkS1R1bFuObgZqDY")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha256,format=e1NBTFR9e1BXRH06OntQRVBQRVJ9,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$GtPTq28+3e9Kzj50rqZPEg$tWKvki8V0bG46arrwtXJSpxIOUfMHTRU0vSRkERILBk"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha256,format=e1NBTFR9e1BXRH06OntQRVBQRVJ9,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$GtPTq28+3e9Kzj50rqZPEg$tWKvki8V0bG46arrwtXJSpxIOUfMHTRU0vSRkERILBk"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha256,format=e1NBTFR9e1BXRH06OntQRVBQRVJ9,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$GtPTq28+3e9Kzj50rqZPEg$tWKvki8V0bG46arrwtXJSpxIOUfMHTRU0vSRkERILBk")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha256,format=e1NBTFR9e1BXRH06OntQRVBQRVJ9,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$GtPTq28+3e9Kzj50rqZPEg$tWKvki8V0bG46arrwtXJSpxIOUfMHTRU0vSRkERILBk")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha256,format=e1BFUFBFUn0tLXtQV0R9e1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ArlRmKGVqgR7QrsCKvrrLA$Cw4wKvkanyWn3Vn2jhDq8274QzipVerz03yMpg4UWPY"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha256,format=e1BFUFBFUn0tLXtQV0R9e1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ArlRmKGVqgR7QrsCKvrrLA$Cw4wKvkanyWn3Vn2jhDq8274QzipVerz03yMpg4UWPY"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha256,format=e1BFUFBFUn0tLXtQV0R9e1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ArlRmKGVqgR7QrsCKvrrLA$Cw4wKvkanyWn3Vn2jhDq8274QzipVerz03yMpg4UWPY")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha256,format=e1BFUFBFUn0tLXtQV0R9e1NBTFR9,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ArlRmKGVqgR7QrsCKvrrLA$Cw4wKvkanyWn3Vn2jhDq8274QzipVerz03yMpg4UWPY")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha256,format=e1NBTFR9IXtQV0R9,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$vdXWDxVzhe8G17+PNaco4w$tkeByklPTjbW4B/MRVcJrnKkkIagASRPNJ8EC6gz484"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha256,format=e1NBTFR9IXtQV0R9,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$vdXWDxVzhe8G17+PNaco4w$tkeByklPTjbW4B/MRVcJrnKkkIagASRPNJ8EC6gz484"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha256,format=e1NBTFR9IXtQV0R9,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$vdXWDxVzhe8G17+PNaco4w$tkeByklPTjbW4B/MRVcJrnKkkIagASRPNJ8EC6gz484")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha256,format=e1NBTFR9IXtQV0R9,i=6$argon2id$v=19$m=65536,t=2,p=2$vdXWDxVzhe8G17+PNaco4w$tkeByklPTjbW4B/MRVcJrnKkkIagASRPNJ8EC6gz484")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha256,format=KntQV0R9KntQRVBQRVJ9,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$1vaPp50rp0k0DKZ+iKX5qg$Xry+1BL0f++GBetTm1k7wVH11rhFAohKfnJyTPi+/FE"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha256,format=KntQV0R9KntQRVBQRVJ9,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$1vaPp50rp0k0DKZ+iKX5qg$Xry+1BL0f++GBetTm1k7wVH11rhFAohKfnJyTPi+/FE"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha256,format=KntQV0R9KntQRVBQRVJ9,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$1vaPp50rp0k0DKZ+iKX5qg$Xry+1BL0f++GBetTm1k7wVH11rhFAohKfnJyTPi+/FE")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha256,format=KntQV0R9KntQRVBQRVJ9,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$1vaPp50rp0k0DKZ+iKX5qg$Xry+1BL0f++GBetTm1k7wVH11rhFAohKfnJyTPi+/FE")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=QHtTQUxUfXtQV0R9e1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$UKi87eOTsSfGej3hJo5Kuw$BTONgT+HNlQDdTDz18hdveHuYvYNV5rUkFMHNCFu4MI"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=QHtTQUxUfXtQV0R9e1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$UKi87eOTsSfGej3hJo5Kuw$BTONgT+HNlQDdTDz18hdveHuYvYNV5rUkFMHNCFu4MI"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=QHtTQUxUfXtQV0R9e1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$UKi87eOTsSfGej3hJo5Kuw$BTONgT+HNlQDdTDz18hdveHuYvYNV5rUkFMHNCFu4MI")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=QHtTQUxUfXtQV0R9e1BFUFBFUn0,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$UKi87eOTsSfGej3hJo5Kuw$BTONgT+HNlQDdTDz18hdveHuYvYNV5rUkFMHNCFu4MI")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0re1BXRH17U0FMVH0,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$l2DaZlfkxfOKvkEyGtoYyQ$Q3gmY/htfhkQMXgq28LGdMY8qkRZegWqku0foPiKd0I"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0re1BXRH17U0FMVH0,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$l2DaZlfkxfOKvkEyGtoYyQ$Q3gmY/htfhkQMXgq28LGdMY8qkRZegWqku0foPiKd0I"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0re1BXRH17U0FMVH0,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$l2DaZlfkxfOKvkEyGtoYyQ$Q3gmY/htfhkQMXgq28LGdMY8qkRZegWqku0foPiKd0I")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0re1BXRH17U0FMVH0,i=4,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$l2DaZlfkxfOKvkEyGtoYyQ$Q3gmY/htfhkQMXgq28LGdMY8qkRZegWqku0foPiKd0I")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BXRH17U0FMVH0,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$QkHu9YeFzSO0iwpBRGJa3A$31EMUPio1HAKxcGjU25+J09Qner9ZasnyFtQnWyQbDk"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BXRH17U0FMVH0,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$QkHu9YeFzSO0iwpBRGJa3A$31EMUPio1HAKxcGjU25+J09Qner9ZasnyFtQnWyQbDk"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BXRH17U0FMVH0,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$QkHu9YeFzSO0iwpBRGJa3A$31EMUPio1HAKxcGjU25+J09Qner9ZasnyFtQnWyQbDk")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BXRH17U0FMVH0,i=6,salt=7aCA$argon2id$v=19$m=65536,t=2,p=2$QkHu9YeFzSO0iwpBRGJa3A$31EMUPio1HAKxcGjU25+J09Qner9ZasnyFtQnWyQbDk")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0me1BXRH0,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ixWTVMO1H+ISmd1Kt0tTzw$u0eyUlDM0d/jCFJIPdkwXyNTEk1ZQrLao6RprRbFDfQ"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0me1BXRH0,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ixWTVMO1H+ISmd1Kt0tTzw$u0eyUlDM0d/jCFJIPdkwXyNTEk1ZQrLao6RprRbFDfQ"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0me1BXRH0,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ixWTVMO1H+ISmd1Kt0tTzw$u0eyUlDM0d/jCFJIPdkwXyNTEk1ZQrLao6RprRbFDfQ")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0me1BXRH0,i=2,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ixWTVMO1H+ISmd1Kt0tTzw$u0eyUlDM0d/jCFJIPdkwXyNTEk1ZQrLao6RprRbFDfQ")), hash.ErrMismatchedHashAndPassword) + + assert.Nil(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4"))) + assert.Nil(t, hash.CompareLegacy(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4"))) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.CompareLegacy(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4")), hash.ErrMismatchedHashAndPassword) + + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password123456"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn17UFdEfXtTQUxUfQ,i=3,salt=7aCA,pepper=/v7//w$argon2id$v=19$m=65536,t=2,p=2$UKi87eOTsSfGej3hJo5Kuw$BTONgT+HNlQDdTDz18hdveHuYvYNV5rUkFMHNCFu4MI")), hash.ErrMismatchedHashAndPassword) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha224,format=e1BFUFBFUn0me1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ixWTVMO1H+ISmd1Kt0tTzw$u0eyUlDM0d/jCFJIPdkwXyNTEk1ZQrLao6RprRbFDfQ")), hash.ErrInvalidHash) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0me1BXRH0,i=0,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ixWTVMO1H+ISmd1Kt0tTzw$u0eyUlDM0d/jCFJIPdkwXyNTEk1ZQrLao6RprRbFDfQ")), hash.ErrInvalidHash) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn0me1BXRH0,i=-1,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ixWTVMO1H+ISmd1Kt0tTzw$u0eyUlDM0d/jCFJIPdkwXyNTEk1ZQrLao6RprRbFDfQ")), hash.ErrInvalidHash) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BFUFBFUn17U0FMVH0,i=1,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$ixWTVMO1H+ISmd1Kt0tTzw$u0eyUlDM0d/jCFJIPdkwXyNTEk1ZQrLao6RprRbFDfQ")), hash.ErrInvalidHash) + + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$algsha512,format=e1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4")), hash.ErrInvalidHash) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$al=sha512,format=e1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4")), hash.ErrInvalidHash) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,format=e1BXRH0,i2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4")), hash.ErrInvalidHash) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,foramt=e1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4")), hash.ErrInvalidHash) + assert.ErrorIs(t, hash.Compare(context.Background(), []byte("Password12345"), []byte("$legacy$alg=sha512,foramt=e1BXRH0,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argn2id$v=19$m=65536,t=2,p=2$0Ymn7jSuYxhJKhxbz+9dtQ$vXZo2f9RflB7/WN1rbQAFQGIxJIKxY7HJKd/Cq4VHA4")), hash.ErrInvalidHash) + }) } diff --git a/test/e2e/cypress/integration/profiles/import/import.spec.ts b/test/e2e/cypress/integration/profiles/import/import.spec.ts index cc54662233d1..65f403f6b0b2 100644 --- a/test/e2e/cypress/integration/profiles/import/import.spec.ts +++ b/test/e2e/cypress/integration/profiles/import/import.spec.ts @@ -47,6 +47,14 @@ context("Import Identities", () => { }, checkPassword: "123456", }, + { + name: "legacy", + config: { + hashed_password: + "$legacy$alg=sha512,format=e1NBTFR9e1BXRH17UEVQUEVSfQ,i=2,salt=YSBzYWx0,pepper=YSBwZXBwZXI$argon2id$v=19$m=65536,t=2,p=2$50KKKea7S6zVD1mw4daJ5Q$XvhuzVysBuAUYtlm6Q0OzX7UhqenPkV5inrvppinFKE", + }, + checkPassword: "123456", + }, ]) { it(`should be able to sign in using an imported password (${tc.name})`, () => { const email = gen.email()