ory/hydra · error
ErrUnknownHashAlgorithm
ErrUnknownHashAlgorithm
Error message
unknown hash algorithm
What it means
hasherx.Compare dispatches on the hash encoding prefix ($argon2id$, $argon2i$, $2a$ bcrypt, $pbkdf2$ etc.). If the hash's algorithm identifier is none of the recognized kinds, Compare returns ErrUnknownHashAlgorithm because it has no comparator for that scheme.
Source
Thrown at oryx/hasherx/hash_comparator.go:18
package hasherx
import (
"context"
"crypto/subtle"
"encoding/base64"
"fmt"
"math"
"regexp"
"strings"
"github.com/pkg/errors"
"golang.org/x/crypto/argon2"
"golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/pbkdf2"
)
var ErrUnknownHashAlgorithm = errors.New("unknown hash algorithm")
// Compare the given password with the given hash.
func Compare(ctx context.Context, password []byte, hash []byte) error {
switch {
case IsBcryptHash(hash):
return CompareBcrypt(ctx, password, hash)
case IsArgon2idHash(hash):
return CompareArgon2id(ctx, password, hash)
case IsArgon2iHash(hash):
return CompareArgon2i(ctx, password, hash)
case IsPbkdf2Hash(hash):
return ComparePbkdf2(ctx, password, hash)
default:
return errors.WithStack(ErrUnknownHashAlgorithm)
}
}
func CompareBcrypt(_ context.Context, password []byte, hash []byte) error {View on GitHub (pinned to 4174065ffb)
Solutions
- Store hashes produced by a supported scheme (bcrypt, argon2id, argon2i, pbkdf2) with their full standard prefix intact.
- Check the stored hash string starts with a supported prefix ($2a/$2b/$2y, $argon2id$, $argon2i$, $pbkdf2) before calling Compare.
- Re-hash imported credentials with a supported hasher on next login (progressive migration) instead of comparing them directly.
- Fix storage/encoding steps that strip or mangle the prefix (e.g. URL-safe base64 rewrites).
Example fix
// before
if !strings.HasPrefix(string(storedHash), "$2") { /* raw sha256 hex */ }
err := hasherx.Compare(ctx, pw, storedHash) // -> unknown hash algorithm
// after
hash, _ := hasherx.BcryptHasher{}.Generate(ctx, pw) // or argon2id hasher
err := hasherx.Compare(ctx, pw, hash) Defensive patterns
Strategy: validation
Validate before calling
func knownHashFormat(hash []byte) bool {
p := string(hash)
return strings.HasPrefix(p, "$2a$") || strings.HasPrefix(p, "$2b$") ||
strings.HasPrefix(p, "$2y$") || strings.HasPrefix(p, "$argon2id$") ||
strings.HasPrefix(p, "$argon2i$") || strings.HasPrefix(p, "$pbkdf2")
}
// guard before Compare Type guard
func isSupportedHash(b []byte) bool { return knownHashFormat(b) } Try / catch
if err := hasherx.Compare(ctx, pw, hash); err != nil {
if errors.Is(err, hasherx.ErrUnknownHashAlgorithm) {
// flag for re-hash/migration instead of failing auth outright
return migrateAndRehash(user, pw)
}
return err
} Prevention
- Only store hashes generated with supported algorithms
- Preserve the full hash string including its algorithm prefix in the DB
- Re-hash imported credentials to a supported scheme
- Add a startup check that fixture/config hashes parse
When it happens
Trigger: Calling Compare(ctx, password, hash) where hash carries an unrecognized identifier (e.g. $scrypt$, a bare SHA-256 hex string, or a truncated/garbled prefix), so the prefix-based switch falls to the default branch.
Common situations: Importing users from another system using an unsupported algorithm, hashes damaged by truncation or base64 re-encoding, hand-crafted test fixtures, or hashes stored without their algorithm prefix.
Related errors
- ErrInvalidHash
- ErrMismatchedHashAndPassword
- ErrIncompatibleVersion
- cookiex: at least one secret is required
- invalid elliptic curve key size, this algorithm does not sup
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/769da834f9772abd.
Report an issue: GitHub.