今天在一個源碼裏面看到裏面的 util 包,裏面的好多的工具都是咱們能夠直接拿來使用的,以前沒有這個習慣,因此每次就喜歡處處找。如今開始在這些源碼裏面去記錄一下。方便往後的使用。git
// 這裏是引入的包 import ( "crypto/rand" "crypto/sha256" "crypto/md5" "encoding/base64" "encoding/hex" "errors" "golang.org/x/crypto/pbkdf2" "strings" "github.com/grafana/grafana/pkg/util/errutil" )
// GetRandomString generate random string by specify chars. // 經過指定字符生成隨機字符串 func GetRandomString(n int, alphabets ...byte) (string, error) { const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" var bytes = make([]byte, n) if _, err := rand.Read(bytes); err != nil { return "", err } for i, b := range bytes { if len(alphabets) == 0 { bytes[i] = alphanum[b%byte(len(alphanum))] } else { bytes[i] = alphabets[b%byte(len(alphabets))] } } return string(bytes), nil } // EncodePassword encodes a password using PBKDF2. // 使用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. // 從用戶和密碼返回base64編碼的字符串。 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. // 從基本的auth標頭解碼用戶和密碼。 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 random string from a n seed. // 從n個種子返回一個隨機字符串。 func RandomHex(n int) (string, error) { bytes := make([]byte, n) if _, err := rand.Read(bytes); err != nil { return "", err } return hex.EncodeToString(bytes), nil }
// Decrypt decrypts a payload with a given secret. func Decrypt(payload []byte, secret string) ([]byte, error) { salt := payload[:saltLength] key, err := encryptionKeyToBytes(secret, string(salt)) if err != nil { return nil, err } block, err := aes.NewCipher(key) if err != nil { return nil, err } // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertext. if len(payload) < aes.BlockSize { return nil, errors.New("payload too short") } iv := payload[saltLength : saltLength+aes.BlockSize] payload = payload[saltLength+aes.BlockSize:] payloadDst := make([]byte, len(payload)) stream := cipher.NewCFBDecrypter(block, iv) // XORKeyStream can work in-place if the two arguments are the same. stream.XORKeyStream(payloadDst, payload) return payloadDst, nil } // Encrypt encrypts a payload with a given secret. func Encrypt(payload []byte, secret string) ([]byte, error) { salt, err := GetRandomString(saltLength) if err != nil { return nil, err } key, err := encryptionKeyToBytes(secret, salt) if err != nil { return nil, err } block, err := aes.NewCipher(key) if err != nil { return nil, err } // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertext. ciphertext := make([]byte, saltLength+aes.BlockSize+len(payload)) copy(ciphertext[:saltLength], []byte(salt)) iv := ciphertext[saltLength : saltLength+aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return nil, err } stream := cipher.NewCFBEncrypter(block, iv) stream.XORKeyStream(ciphertext[saltLength+aes.BlockSize:], payload) return ciphertext, nil } // Key needs to be 32bytes func encryptionKeyToBytes(secret, salt string) ([]byte, error) { return pbkdf2.Key([]byte(secret), []byte(salt), 10000, 32, sha256.New), nil }
// Md5Sum calculates the md5sum of a stream // 計算流的md5sum func Md5Sum(reader io.Reader) (string, error) { var returnMD5String string hash := md5.New() if _, err := io.Copy(hash, reader); err != nil { return returnMD5String, err } hashInBytes := hash.Sum(nil)[:16] returnMD5String = hex.EncodeToString(hashInBytes) return returnMD5String, nil } // Md5SumString calculates the md5sum of a string // 計算字符串的md5sum func Md5SumString(input string) (string, error) { buffer := strings.NewReader(input) return Md5Sum(buffer) }
// ParseIPAddress parses an IP address and removes port and/or IPV6 format func ParseIPAddress(input string) (string, error) { addr, err := SplitHostPort(input) if err != nil { return "", errutil.Wrapf(err, "Failed to split network address '%s' by host and port", input) } ip := net.ParseIP(addr.Host) if ip == nil { return addr.Host, nil } if ip.IsLoopback() { if strings.Contains(addr.Host, ":") { // IPv6 return "::1", nil } return "127.0.0.1", nil } return ip.String(), nil } type NetworkAddress struct { Host string Port string } // SplitHostPortDefault splits ip address/hostname string by host and port. Defaults used if no match found func SplitHostPortDefault(input, defaultHost, defaultPort string) (NetworkAddress, error) { addr := NetworkAddress{ Host: defaultHost, Port: defaultPort, } if len(input) == 0 { return addr, nil } start := 0 // Determine if IPv6 address, in which case IP address will be enclosed in square brackets if strings.Index(input, "[") == 0 { addrEnd := strings.LastIndex(input, "]") if addrEnd < 0 { // Malformed address return addr, fmt.Errorf("Malformed IPv6 address: '%s'", input) } start = addrEnd } if strings.LastIndex(input[start:], ":") < 0 { // There's no port section of the input // It's still useful to call net.SplitHostPort though, since it removes IPv6 // square brackets from the address input = fmt.Sprintf("%s:%s", input, defaultPort) } host, port, err := net.SplitHostPort(input) if err != nil { return addr, errutil.Wrapf(err, "net.SplitHostPort failed for '%s'", input) } if len(host) > 0 { addr.Host = host } if len(port) > 0 { addr.Port = port } return addr, nil } // SplitHostPort splits ip address/hostname string by host and port func SplitHostPort(input string) (NetworkAddress, error) { if len(input) == 0 { return NetworkAddress{}, fmt.Errorf("Input is empty") } return SplitHostPortDefault(input, "", "") }