package usos import ( "crypto/hmac" "crypto/rand" "crypto/sha1" "encoding/base64" "encoding/hex" "net/url" "sort" "strconv" "strings" "time" ) const unreserved = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~" func percentEncode(s string) string { var b strings.Builder for i := range len(s) { c := s[i] if strings.IndexByte(unreserved, c) >= 0 { b.WriteByte(c) continue } b.WriteByte('%') b.WriteString(strings.ToUpper(hex.EncodeToString([]byte{c}))) } return b.String() } func signature(method, endpoint string, params url.Values, consumerSecret, tokenSecret string) string { pairs := make([]string, 0, len(params)) for key, values := range params { for _, value := range values { pairs = append(pairs, percentEncode(key)+"="+percentEncode(value)) } } sort.Strings(pairs) base := method + "&" + percentEncode(endpoint) + "&" + percentEncode(strings.Join(pairs, "&")) mac := hmac.New(sha1.New, []byte(percentEncode(consumerSecret)+"&"+percentEncode(tokenSecret))) mac.Write([]byte(base)) return base64.StdEncoding.EncodeToString(mac.Sum(nil)) } func nonce() string { buf := make([]byte, 16) if _, err := rand.Read(buf); err != nil { panic(err) } return hex.EncodeToString(buf) } func (c *Client) authorization(endpoint string, token *Token, params url.Values) (header string, body url.Values) { oauth := url.Values{ "oauth_consumer_key": {c.Key}, "oauth_nonce": {nonce()}, "oauth_signature_method": {"HMAC-SHA1"}, "oauth_timestamp": {strconv.FormatInt(time.Now().Unix(), 10)}, "oauth_version": {"1.0"}, } tokenSecret := "" if token != nil { oauth.Set("oauth_token", token.Key) tokenSecret = token.Secret } body = url.Values{} all := url.Values{} for key, values := range params { if strings.HasPrefix(key, "oauth_") { oauth[key] = values } else { body[key] = values } all[key] = values } for key, values := range oauth { all[key] = values } oauth.Set("oauth_signature", signature("POST", endpoint, all, c.Secret, tokenSecret)) keys := make([]string, 0, len(oauth)) for key := range oauth { keys = append(keys, key) } sort.Strings(keys) parts := make([]string, 0, len(keys)) for _, key := range keys { parts = append(parts, key+`="`+percentEncode(oauth.Get(key))+`"`) } return "OAuth " + strings.Join(parts, ", "), body }