snapshot of https://github.com/ory/keto.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
103
oryx/hasherx/hasher_pbkdf2.go
Normal file
103
oryx/hasherx/hasher_pbkdf2.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package hasherx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/sha1" // #nosec G505 - compatibility for imported passwords
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"hash"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
"github.com/ory/x/otelx"
|
||||
)
|
||||
|
||||
type (
|
||||
// PBKDF2 is a PBKDF2 hasher.
|
||||
PBKDF2 struct {
|
||||
c PBKDF2Configurator
|
||||
}
|
||||
|
||||
// PBKDF2Config is the configuration for a PBKDF2 hasher.
|
||||
PBKDF2Config struct {
|
||||
// Algorithm can be one of sha1, sha224, sha256, sha384, sha512
|
||||
Algorithm string
|
||||
// Iterations is the number of iterations to use.
|
||||
Iterations uint32
|
||||
// KeyLength is the length of the salt.
|
||||
SaltLength uint32
|
||||
// KeyLength is the length of the key.
|
||||
KeyLength uint32
|
||||
}
|
||||
|
||||
// PBKDF2Configurator is a configurator for a PBKDF2 hasher.
|
||||
PBKDF2Configurator interface {
|
||||
HasherPBKDF2Config(ctx context.Context) *PBKDF2Config
|
||||
}
|
||||
)
|
||||
|
||||
// NewHasherPBKDF2 creates a new PBKDF2 hasher.
|
||||
func NewHasherPBKDF2(c PBKDF2Configurator) *PBKDF2 {
|
||||
return &PBKDF2{c: c}
|
||||
}
|
||||
|
||||
// Generate generates a hash for the given password.
|
||||
func (h *PBKDF2) Generate(ctx context.Context, password []byte) (hash []byte, err error) {
|
||||
ctx, span := otel.GetTracerProvider().Tracer("").Start(ctx, "hash.PBKDF2.Generate")
|
||||
defer otelx.End(span, &err)
|
||||
|
||||
conf := h.c.HasherPBKDF2Config(ctx)
|
||||
salt := make([]byte, conf.SaltLength)
|
||||
if _, err := rand.Read(salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key := pbkdf2.Key(password, salt, int(conf.Iterations), int(conf.KeyLength), getPseudorandomFunctionForPbkdf2(conf.Algorithm))
|
||||
|
||||
var b bytes.Buffer
|
||||
if _, err := fmt.Fprintf(
|
||||
&b,
|
||||
"$pbkdf2-%s$i=%d,l=%d$%s$%s",
|
||||
conf.Algorithm,
|
||||
conf.Iterations,
|
||||
conf.KeyLength,
|
||||
base64.RawStdEncoding.EncodeToString(salt),
|
||||
base64.RawStdEncoding.EncodeToString(key),
|
||||
); err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// Understands checks if the given hash is in the correct format.
|
||||
func (h *PBKDF2) Understands(hash []byte) bool {
|
||||
return IsPbkdf2Hash(hash)
|
||||
}
|
||||
|
||||
func getPseudorandomFunctionForPbkdf2(alg string) func() hash.Hash {
|
||||
switch alg {
|
||||
case "sha1":
|
||||
return sha1.New
|
||||
case "sha224":
|
||||
return sha3.New224
|
||||
case "sha256":
|
||||
return sha256.New
|
||||
case "sha384":
|
||||
return sha3.New384
|
||||
case "sha512":
|
||||
return sha512.New
|
||||
default:
|
||||
return sha256.New
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user