package fic import ( "bytes" "crypto/md5" "regexp" "strings" ) // ToURLid converts the given string to a valid URLid. func ToURLid(str string) string { re := regexp.MustCompile("[^a-zA-Z0-9]+") return strings.TrimSuffix(re.ReplaceAllLiteralString(str, "-"), "-") } // Apr1Md5 computes a usable hash for basic auth in Apache and nginx. // Function copied from https://github.com/jimstudt/http-authentication/blob/master/basic/md5.go // as it was not exported in package and comes with other unwanted functions. // Original source code under MIT. func Apr1Md5(password string, salt string) string { initBin := md5.Sum([]byte(password + salt + password)) initText := bytes.NewBufferString(password + "$apr1$" + salt) for i := len(password); i > 0; i -= 16 { lim := i if lim > 16 { lim = 16 } initText.Write(initBin[0:lim]) } for i := len(password); i > 0; i >>= 1 { if (i & 1) == 1 { initText.WriteByte(byte(0)) } else { initText.WriteByte(password[0]) } } bin := md5.Sum(initText.Bytes()) n := bytes.NewBuffer([]byte{}) for i := 0; i < 1000; i++ { n.Reset() if (i & 1) == 1 { n.WriteString(password) } else { n.Write(bin[:]) } if i%3 != 0 { n.WriteString(salt) } if i%7 != 0 { n.WriteString(password) } if (i & 1) == 1 { n.Write(bin[:]) } else { n.WriteString(password) } bin = md5.Sum(n.Bytes()) } result := bytes.NewBuffer([]byte{}) fill := func(a byte, b byte, c byte) { v := (uint(a) << 16) + (uint(b) << 8) + uint(c) for i := 0; i < 4; i++ { result.WriteByte("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[v&0x3f]) v >>= 6 } } fill(bin[0], bin[6], bin[12]) fill(bin[1], bin[7], bin[13]) fill(bin[2], bin[8], bin[14]) fill(bin[3], bin[9], bin[15]) fill(bin[4], bin[10], bin[5]) fill(0, 0, bin[11]) resultString := string(result.Bytes()[0:22]) return resultString }