package crypto import ( "crypto/sha512" "encoding/hex" "github.com/xdg-go/pbkdf2" "edge-infra.dev/pkg/lib/crypto/randomizer" "edge-infra.dev/pkg/lib/crypto/validation" ) type pbkdf2Credential struct { plainTextPwd string hashedPwd []byte iterations int salt []byte } func (pwd pbkdf2Credential) Salt() ([]byte, error) { return pwd.salt, nil } func (pwd pbkdf2Credential) Iterations() (int, error) { return pwd.iterations, nil } func (pwd pbkdf2Credential) HashFunction() string { return string(pbkdf2Type) } func (pwd pbkdf2Credential) HashType() string { return pbkdf2Type.Type() } func (pwd pbkdf2Credential) Hashed() []byte { return pwd.hashedPwd } func (pwd pbkdf2Credential) Plain() string { return pwd.plainTextPwd } // Generates a random hashed password using pdkdf2 func GenerateRandomPbkdf2Password(minLength, maxLength, iterations, saltLength, keyLength int) (Credential, error) { if err := validation.ValidatePwdBounds(minLength, maxLength); err != nil { return nil, err } pwdLen, err := randomizer.RandomPassLength(minLength, maxLength) if err != nil { return nil, err } if err := validation.ValidateSaltLength(saltLength); err != nil { return nil, err } if err := validation.ValidateIterationLen(iterations); err != nil { return nil, err } if err = validation.ValidateKeyLen(keyLength, saltLength); err != nil { return nil, err } pwd, err := randomizer.GenerateRandomPlainPwd(pwdLen) if err != nil { return nil, err } salt, err := randomizer.GenerateRandomSalt(saltLength) if err != nil { return nil, err } hashedPwd := hashPbkdf2([]byte(pwd), []byte(salt), iterations, keyLength) return pbkdf2Credential{plainTextPwd: pwd, hashedPwd: hashedPwd, iterations: iterations, salt: []byte(salt)}, nil } func GeneratePbkdf2Password(pwd string, iterations, saltLength, keyLength int) (Credential, error) { if err := validation.ValidatePwdLen(len(pwd)); err != nil { return nil, err } if err := validation.ValidateSaltLength(saltLength); err != nil { return nil, err } if err := validation.ValidateIterationLen(iterations); err != nil { return nil, err } if err := validation.ValidateKeyLen(keyLength, saltLength); err != nil { return nil, err } salt, err := randomizer.GenerateRandomSalt(saltLength) if err != nil { return nil, err } hashedPwd := hashPbkdf2([]byte(pwd), []byte(salt), iterations, keyLength) return pbkdf2Credential{plainTextPwd: pwd, hashedPwd: hashedPwd, iterations: iterations, salt: []byte(salt)}, nil } func hashPbkdf2(pwd, salt []byte, iterations, keyLength int) []byte { return pbkdf2.Key(pwd, salt, iterations, keyLength, sha512.New) } func ComparePbkdf2HashAndPassword(hash, salt []byte, pwd string, iterations, keyLength int) bool { pwdHash := hashPbkdf2([]byte(pwd), salt, iterations, keyLength) return hex.EncodeToString(pwdHash) == hex.EncodeToString(hash) }