mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-03 12:07:54 +00:00
VAULT-13614 Support SCRAM-SHA-256 encrypted passwords for PostgreSQL (#19616)
This commit is contained in:
86
plugins/database/postgresql/scram/scram.go
Normal file
86
plugins/database/postgresql/scram/scram.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package scram
|
||||
|
||||
//
|
||||
// @see https://github.com/postgres/postgres/blob/c30f54ad732ca5c8762bb68bbe0f51de9137dd72/src/interfaces/libpq/fe-auth.c#L1167-L1285
|
||||
// @see https://github.com/postgres/postgres/blob/e6bdfd9700ebfc7df811c97c2fc46d7e94e329a2/src/interfaces/libpq/fe-auth-scram.c#L868-L905
|
||||
// @see https://github.com/postgres/postgres/blob/c30f54ad732ca5c8762bb68bbe0f51de9137dd72/src/port/pg_strong_random.c#L66-L96
|
||||
// @see https://github.com/postgres/postgres/blob/e6bdfd9700ebfc7df811c97c2fc46d7e94e329a2/src/common/scram-common.c#L160-L274
|
||||
// @see https://github.com/postgres/postgres/blob/e6bdfd9700ebfc7df811c97c2fc46d7e94e329a2/src/common/scram-common.c#L27-L85
|
||||
|
||||
// Implementation from https://github.com/supercaracal/scram-sha-256/blob/d3c05cd927770a11c6e12de3e3a99c3446a1f78d/main.go
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
)
|
||||
|
||||
const (
|
||||
// @see https://github.com/postgres/postgres/blob/e6bdfd9700ebfc7df811c97c2fc46d7e94e329a2/src/include/common/scram-common.h#L36-L41
|
||||
saltSize = 16
|
||||
|
||||
// @see https://github.com/postgres/postgres/blob/c30f54ad732ca5c8762bb68bbe0f51de9137dd72/src/include/common/sha2.h#L22
|
||||
digestLen = 32
|
||||
|
||||
// @see https://github.com/postgres/postgres/blob/e6bdfd9700ebfc7df811c97c2fc46d7e94e329a2/src/include/common/scram-common.h#L43-L47
|
||||
iterationCnt = 4096
|
||||
)
|
||||
|
||||
var (
|
||||
clientRawKey = []byte("Client Key")
|
||||
serverRawKey = []byte("Server Key")
|
||||
)
|
||||
|
||||
func genSalt(size int) ([]byte, error) {
|
||||
salt := make([]byte, size)
|
||||
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return salt, nil
|
||||
}
|
||||
|
||||
func encodeB64(src []byte) (dst []byte) {
|
||||
dst = make([]byte, base64.StdEncoding.EncodedLen(len(src)))
|
||||
base64.StdEncoding.Encode(dst, src)
|
||||
return
|
||||
}
|
||||
|
||||
func getHMACSum(key, msg []byte) []byte {
|
||||
h := hmac.New(sha256.New, key)
|
||||
_, _ = h.Write(msg)
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
func getSHA256Sum(key []byte) []byte {
|
||||
h := sha256.New()
|
||||
_, _ = h.Write(key)
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
func hashPassword(rawPassword, salt []byte, iter, keyLen int) string {
|
||||
digestKey := pbkdf2.Key(rawPassword, salt, iter, keyLen, sha256.New)
|
||||
clientKey := getHMACSum(digestKey, clientRawKey)
|
||||
storedKey := getSHA256Sum(clientKey)
|
||||
serverKey := getHMACSum(digestKey, serverRawKey)
|
||||
|
||||
return fmt.Sprintf("SCRAM-SHA-256$%d:%s$%s:%s",
|
||||
iter,
|
||||
string(encodeB64(salt)),
|
||||
string(encodeB64(storedKey)),
|
||||
string(encodeB64(serverKey)),
|
||||
)
|
||||
}
|
||||
|
||||
func Hash(password string) (string, error) {
|
||||
salt, err := genSalt(saltSize)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
hashedPassword := hashPassword([]byte(password), salt, iterationCnt, digestLen)
|
||||
return hashedPassword, nil
|
||||
}
|
||||
Reference in New Issue
Block a user