func hashSignature(signingKey string, baseString string) string {
	h := hmac.New(sha1.New, []byte(signingKey))
	h.Write([]byte(baseString))
	return encodeURI(base64.StdEncoding.EncodeToString(h.Sum(nil)))
}
hashSignature creates a HMAC-SHA1 hash
Reference: https://tools.ietf.org/html/rfc5849#section-3.4.2
package oauth1protocol
import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"math/rand"
	gohttp "net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"text/template"
	"time"
)
type OAuth1 struct {
	ConsumerKey     string
	ConsumerSecret  string
	Nonce           string
	Signature       string
	SignatureMethod string
	TimeStamp       string
	Token           string
	TokenSecret     string
	Version         string
}
const (
	oauthConsumerKey     = "oauth_consumer_key"
	oauthNonce           = "oauth_nonce"
	oauthSignatureMethod = "oauth_signature_method"
	oauthTimestamp       = "oauth_timestamp"
	oauthToken           = "oauth_token"
	oauthVersion         = "oauth_version"
)
const (
	nonceCharset = "abcdefghijklmnopqrstuvwxyz" +
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
		"0123456789"
	nonceLength = 16
	oauthSignatureMethodType = "HMAC-SHA1"
	oauthVersionNumber       = "1.0"
)
const (
	consumerKey    = "consumer_key"
	consumerSecret = "consumer_secret"
	token          = "token"
	tokenSecret    = "token_secret"
)
var requiredConfigParams = []string{
	consumerKey,
	consumerSecret,
	token,
	tokenSecret,
}
func generateNonce(length int, charset string) string {
	seededRand := rand.New(
		rand.NewSource(time.Now().UnixNano()))
	randomChars := make([]byte, length)
	for index := range randomChars {
		randomChars[index] = charset[seededRand.Intn(len(charset))]
	}
	return string(randomChars)
}
func checkRequiredOAuthParams(params map[string]string) error {
	for _, requiredParam := range requiredConfigParams {
		if len(params[requiredParam]) < 1 {
			return fmt.Errorf("required oAuth1 parameter '%s' not found", requiredParam)
		}
	}
	return nil
}
func extractOAuthParams(params map[string]string) OAuth1 {
	oauth := OAuth1{
		ConsumerKey:     params[consumerKey],
		ConsumerSecret:  params[consumerSecret],
		Nonce:           generateNonce(nonceLength, nonceCharset),
		SignatureMethod: oauthSignatureMethodType,
		Token:           params[token],
		TokenSecret:     params[tokenSecret],
		TimeStamp:       strconv.Itoa(int(time.Now().Unix())),
		Version:         oauthVersionNumber,
	}
	return oauth
}
func encodeURI(stringToEncode string) string {
	return strings.ReplaceAll(url.QueryEscape(stringToEncode), "+", "%20")
}
func collectParameters(oauth1 OAuth1, r *gohttp.Request) map[string][]string {
	buf, _ := ioutil.ReadAll(r.Body)
	originalBody := ioutil.NopCloser(bytes.NewBuffer(buf))
	copyBody := ioutil.NopCloser(bytes.NewBuffer(buf))
	r.Body = originalBody
	paramMap := make(map[string][]string, 0)
	r.ParseForm()
	for paramKey, paramValues := range r.Form {
		encodedKey := encodeURI(paramKey)
		paramMap[encodedKey] = paramValues
		for valueIndex, value := range paramMap[encodedKey] {
			encodedValue := encodeURI(value)
			paramMap[encodedKey][valueIndex] = encodedValue
		}
		sort.Strings(paramMap[encodedKey])
	}
	r.Body = copyBody
	paramMap[oauthConsumerKey] = []string{encodeURI(oauth1.ConsumerKey)}
	paramMap[oauthNonce] = []string{encodeURI(oauth1.Nonce)}
	paramMap[oauthSignatureMethod] = []string{encodeURI(oauth1.SignatureMethod)}
	paramMap[oauthTimestamp] = []string{encodeURI(oauth1.TimeStamp)}
	paramMap[oauthToken] = []string{encodeURI(oauth1.Token)}
	paramMap[oauthVersion] = []string{encodeURI(oauth1.Version)}
	return paramMap
}
func generateParameterString(paramMap map[string][]string) string {
	var parameterString strings.Builder
	keys := make([]string, 0, len(paramMap))
	for key := range paramMap {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	for keyIndex, key := range keys {
		for valueIndex, value := range paramMap[key] {
			if keyIndex > 0 || valueIndex > 0 {
				parameterString.WriteString("&")
			}
			parameterString.WriteString(key + "=" + value)
		}
	}
	return parameterString.String()
}
func generateBaseString(r *gohttp.Request, paramString string) string {
	method := strings.ToUpper(r.Method)
	urlString := fmt.Sprintf("%s://%s%s", r.URL.Scheme, r.URL.Host, r.URL.Path)
	return fmt.Sprintf("%s&%s&%s", method, encodeURI(urlString), encodeURI(paramString))
}
func generateSigningKey(oauth1 OAuth1) string {
	return fmt.Sprintf("%s&%s", encodeURI(oauth1.ConsumerSecret), encodeURI(oauth1.TokenSecret))
}