93 lines
2.3 KiB
Go
93 lines
2.3 KiB
Go
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
|
|
}
|