package util import ( "crypto/hmac" "crypto/md5" "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/hex" "errors" "fmt" "hash" "strings" ) // source: https://github.com/gogits/gogs/blob/9ee80e3e5426821f03a4e99fad34418f5c736413/modules/base/tool.go#L58 func GetRandomString(n int, alphabets ...byte) string { const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" var bytes = make([]byte, n) rand.Read(bytes) 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) } func EncodePassword(password string, salt string) string { newPasswd := PBKDF2([]byte(password), []byte(salt), 10000, 50, sha256.New) return fmt.Sprintf("%x", newPasswd) } // Encode string to md5 hex value. func EncodeMd5(str string) string { m := md5.New() m.Write([]byte(str)) return hex.EncodeToString(m.Sum(nil)) } // http://code.google.com/p/go/source/browse/pbkdf2/pbkdf2.go?repo=crypto func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { prf := hmac.New(h, password) hashLen := prf.Size() numBlocks := (keyLen + hashLen - 1) / hashLen var buf [4]byte dk := make([]byte, 0, numBlocks*hashLen) U := make([]byte, hashLen) for block := 1; block <= numBlocks; block++ { // N.B.: || means concatenation, ^ means XOR // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter // U_1 = PRF(password, salt || uint(i)) prf.Reset() prf.Write(salt) buf[0] = byte(block >> 24) buf[1] = byte(block >> 16) buf[2] = byte(block >> 8) buf[3] = byte(block) prf.Write(buf[:4]) dk = prf.Sum(dk) T := dk[len(dk)-hashLen:] copy(U, T) // U_n = PRF(password, U_(n-1)) for n := 2; n <= iter; n++ { prf.Reset() prf.Write(U) U = U[:0] U = prf.Sum(U) for x := range U { T[x] ^= U[x] } } } return dk[:keyLen] } func GetBasicAuthHeader(user string, password string) string { var userAndPass = user + ":" + password return "Basic " + base64.StdEncoding.EncodeToString([]byte(userAndPass)) } 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 }