go-passwd/pbkdf1_sha1_crypt.go
2024-09-07 18:40:13 -05:00

71 lines
1.7 KiB
Go

package passwd
import (
"crypto/hmac"
"crypto/sha1"
"fmt"
"strconv"
)
type SHA1Crypt struct {
Passwd
}
func NewSHA1Passwd() PasswdInterface {
m := new(SHA1Crypt)
m.Magic = SHA1_CRYPT_MAGIC
m.Params = "262144"
m.i = m
return m
}
// PBKDF1 with SHA1 crypt algorithm.
func (a *SHA1Crypt) Hash(password []byte, salt []byte, iterations uint64) (hash []byte) {
// We store the magic bytes as a string as we use sprintf to
// encode the outputs and easily translate the iterations
// from an uint64 to a string.
magic := a.Magic
// The first bit we encode into the hmac is the salt,
// magic string, and iterations of hmac rounds.
output := fmt.Sprintf("%s%s%d", salt, magic, iterations)
// Setup hmac with the password as the key.
hm := hmac.New(sha1.New, password)
// Write the salt and parameters to the hmac.
hm.Write([]byte(output))
// Get the first sum for the iterrations.
buf := hm.Sum(nil)
// Iterate the hmac to the specified number of iterations.
for i := uint64(1); i < iterations; i++ {
// Setup the hmac for this iteration.
hm.Reset()
// Feed back in the buffer from the last iteration.
hm.Write(buf)
// Get the buffer from this iteration.
buf = hm.Sum(nil)
}
// Create hash with result.
b64 := Base64Encode(buf)
hash = []byte(fmt.Sprintf("%s%d$%s$", magic, iterations, salt))
hash = append(hash, b64...)
return
}
// Override the hash with salt function to encode PBKDF1 with SHA1 hash.
func (a *SHA1Crypt) HashPasswordWithSalt(password []byte, salt []byte) (hash []byte, err error) {
iterations, err := strconv.ParseUint(a.Params, 10, 64)
if err != nil {
return nil, err
}
hash = a.Hash(password, salt, iterations)
return
}