mirror of
https://github.com/grafana/grafana.git
synced 2024-12-25 16:31:28 -06:00
7e765c870a
* reimplement GetRandomString, add tests that results are unbiased
102 lines
2.4 KiB
Go
102 lines
2.4 KiB
Go
package util
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"errors"
|
|
"io"
|
|
"mime/quotedprintable"
|
|
"strings"
|
|
|
|
"golang.org/x/crypto/pbkdf2"
|
|
)
|
|
|
|
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
|
|
// GetRandomString generates a random alphanumeric string of the specified length,
|
|
// optionally using only specified characters
|
|
func GetRandomString(n int, alphabets ...byte) (string, error) {
|
|
chars := alphanum
|
|
if len(alphabets) > 0 {
|
|
chars = string(alphabets)
|
|
}
|
|
cnt := len(chars)
|
|
max := 255 / cnt * cnt
|
|
|
|
bytes := make([]byte, n)
|
|
|
|
randread := n * 5 / 4
|
|
randbytes := make([]byte, randread)
|
|
|
|
for i := 0; i < n; {
|
|
if _, err := rand.Read(randbytes); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
for j := 0; i < n && j < randread; j++ {
|
|
b := int(randbytes[j])
|
|
if b >= max {
|
|
continue
|
|
}
|
|
|
|
bytes[i] = chars[b%cnt]
|
|
i++
|
|
}
|
|
}
|
|
|
|
return string(bytes), nil
|
|
}
|
|
|
|
// EncodePassword encodes a password using PBKDF2.
|
|
func EncodePassword(password string, salt string) (string, error) {
|
|
newPasswd := pbkdf2.Key([]byte(password), []byte(salt), 10000, 50, sha256.New)
|
|
return hex.EncodeToString(newPasswd), nil
|
|
}
|
|
|
|
// GetBasicAuthHeader returns a base64 encoded string from user and password.
|
|
func GetBasicAuthHeader(user string, password string) string {
|
|
var userAndPass = user + ":" + password
|
|
return "Basic " + base64.StdEncoding.EncodeToString([]byte(userAndPass))
|
|
}
|
|
|
|
// DecodeBasicAuthHeader decodes user and password from a basic auth header.
|
|
func DecodeBasicAuthHeader(header string) (string, string, error) {
|
|
var code string
|
|
parts := strings.SplitN(header, " ", 2)
|
|
if len(parts) == 2 && parts[0] == "Basic" {
|
|
code = parts[1]
|
|
}
|
|
|
|
decoded, err := base64.StdEncoding.DecodeString(code)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
userAndPass := strings.SplitN(string(decoded), ":", 2)
|
|
if len(userAndPass) != 2 {
|
|
return "", "", errors.New("invalid basic auth header")
|
|
}
|
|
|
|
return userAndPass[0], userAndPass[1], nil
|
|
}
|
|
|
|
// RandomHex returns a hex encoding of n random bytes.
|
|
func RandomHex(n int) (string, error) {
|
|
bytes := make([]byte, n)
|
|
if _, err := rand.Read(bytes); err != nil {
|
|
return "", err
|
|
}
|
|
return hex.EncodeToString(bytes), nil
|
|
}
|
|
|
|
// decodeQuotedPrintable decodes quoted-printable UTF-8 string
|
|
func DecodeQuotedPrintable(encodedValue string) string {
|
|
decodedBytes, err := io.ReadAll(quotedprintable.NewReader(strings.NewReader(encodedValue)))
|
|
if err != nil {
|
|
return encodedValue
|
|
}
|
|
return string(decodedBytes)
|
|
}
|