github.com/aliyun/credentials-go@v1.4.7/credentials/internal/utils/utils.go (about)

     1  package utils
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	"crypto/hmac"
     7  	"crypto/md5"
     8  	"crypto/rand"
     9  	"crypto/rsa"
    10  	"crypto/sha1"
    11  	"crypto/x509"
    12  	"encoding/base64"
    13  	"encoding/hex"
    14  	"fmt"
    15  	"hash"
    16  	"io"
    17  	mathrand "math/rand"
    18  	"net/url"
    19  	"os"
    20  	"runtime"
    21  	"strconv"
    22  	"sync/atomic"
    23  	"time"
    24  )
    25  
    26  type uuid [16]byte
    27  
    28  const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    29  
    30  var hookRead = func(fn func(p []byte) (n int, err error)) func(p []byte) (n int, err error) {
    31  	return fn
    32  }
    33  
    34  var hookRSA = func(fn func(rand io.Reader, priv *rsa.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)) func(rand io.Reader, priv *rsa.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
    35  	return fn
    36  }
    37  
    38  // GetUUID returns a uuid
    39  func GetUUID() (uuidHex string) {
    40  	uuid := newUUID()
    41  	uuidHex = hex.EncodeToString(uuid[:])
    42  	return
    43  }
    44  
    45  // RandStringBytes returns a rand string
    46  func RandStringBytes(n int) string {
    47  	b := make([]byte, n)
    48  	for i := range b {
    49  		b[i] = letterBytes[mathrand.Intn(len(letterBytes))]
    50  	}
    51  	return string(b)
    52  }
    53  
    54  // ShaHmac1 return a string which has been hashed
    55  func ShaHmac1(source, secret string) string {
    56  	key := []byte(secret)
    57  	hmac := hmac.New(sha1.New, key)
    58  	hmac.Write([]byte(source))
    59  	signedBytes := hmac.Sum(nil)
    60  	signedString := base64.StdEncoding.EncodeToString(signedBytes)
    61  	return signedString
    62  }
    63  
    64  // Sha256WithRsa return a string which has been hashed with Rsa
    65  func Sha256WithRsa(source, secret string) string {
    66  	decodeString, err := base64.StdEncoding.DecodeString(secret)
    67  	if err != nil {
    68  		panic(err)
    69  	}
    70  	private, err := x509.ParsePKCS8PrivateKey(decodeString)
    71  	if err != nil {
    72  		panic(err)
    73  	}
    74  
    75  	h := crypto.Hash.New(crypto.SHA256)
    76  	h.Write([]byte(source))
    77  	hashed := h.Sum(nil)
    78  	signature, err := hookRSA(rsa.SignPKCS1v15)(rand.Reader, private.(*rsa.PrivateKey),
    79  		crypto.SHA256, hashed)
    80  	if err != nil {
    81  		panic(err)
    82  	}
    83  
    84  	return base64.StdEncoding.EncodeToString(signature)
    85  }
    86  
    87  // GetMD5Base64 returns a string which has been base64
    88  func GetMD5Base64(bytes []byte) (base64Value string) {
    89  	md5Ctx := md5.New()
    90  	md5Ctx.Write(bytes)
    91  	md5Value := md5Ctx.Sum(nil)
    92  	base64Value = base64.StdEncoding.EncodeToString(md5Value)
    93  	return
    94  }
    95  
    96  // GetTimeInFormatISO8601 returns a time string
    97  func GetTimeInFormatISO8601() (timeStr string) {
    98  	gmt := time.FixedZone("GMT", 0)
    99  
   100  	return time.Now().In(gmt).Format("2006-01-02T15:04:05Z")
   101  }
   102  
   103  // GetURLFormedMap returns a url encoded string
   104  func GetURLFormedMap(source map[string]string) (urlEncoded string) {
   105  	urlEncoder := url.Values{}
   106  	for key, value := range source {
   107  		urlEncoder.Add(key, value)
   108  	}
   109  	urlEncoded = urlEncoder.Encode()
   110  	return
   111  }
   112  
   113  func newUUID() uuid {
   114  	ns := uuid{}
   115  	safeRandom(ns[:])
   116  	u := newFromHash(md5.New(), ns, RandStringBytes(16))
   117  	u[6] = (u[6] & 0x0f) | (byte(2) << 4)
   118  	u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
   119  
   120  	return u
   121  }
   122  
   123  func newFromHash(h hash.Hash, ns uuid, name string) uuid {
   124  	u := uuid{}
   125  	h.Write(ns[:])
   126  	h.Write([]byte(name))
   127  	copy(u[:], h.Sum(nil))
   128  
   129  	return u
   130  }
   131  
   132  func safeRandom(dest []byte) {
   133  	if _, err := hookRead(rand.Read)(dest); err != nil {
   134  		panic(err)
   135  	}
   136  }
   137  
   138  func (u uuid) String() string {
   139  	buf := make([]byte, 36)
   140  
   141  	hex.Encode(buf[0:8], u[0:4])
   142  	buf[8] = '-'
   143  	hex.Encode(buf[9:13], u[4:6])
   144  	buf[13] = '-'
   145  	hex.Encode(buf[14:18], u[6:8])
   146  	buf[18] = '-'
   147  	hex.Encode(buf[19:23], u[8:10])
   148  	buf[23] = '-'
   149  	hex.Encode(buf[24:], u[10:])
   150  
   151  	return string(buf)
   152  }
   153  
   154  var processStartTime int64 = time.Now().UnixNano() / 1e6
   155  var seqId int64 = 0
   156  
   157  func getGID() uint64 {
   158  	// https://blog.sgmansfield.com/2015/12/goroutine-ids/
   159  	b := make([]byte, 64)
   160  	b = b[:runtime.Stack(b, false)]
   161  	b = bytes.TrimPrefix(b, []byte("goroutine "))
   162  	b = b[:bytes.IndexByte(b, ' ')]
   163  	n, _ := strconv.ParseUint(string(b), 10, 64)
   164  	return n
   165  }
   166  
   167  func GetNonce() (uuidHex string) {
   168  	routineId := getGID()
   169  	currentTime := time.Now().UnixNano() / 1e6
   170  	seq := atomic.AddInt64(&seqId, 1)
   171  	randNum := mathrand.Int63()
   172  	msg := fmt.Sprintf("%d-%d-%d-%d-%d", processStartTime, routineId, currentTime, seq, randNum)
   173  	h := md5.New()
   174  	h.Write([]byte(msg))
   175  	return hex.EncodeToString(h.Sum(nil))
   176  }
   177  
   178  // Get first non-empty value
   179  func GetDefaultString(values ...string) string {
   180  	for _, v := range values {
   181  		if v != "" {
   182  			return v
   183  		}
   184  	}
   185  
   186  	return ""
   187  }
   188  
   189  // set back the memoried enviroment variables
   190  type Rollback func()
   191  
   192  func Memory(keys ...string) Rollback {
   193  	// remenber enviroment variables
   194  	m := make(map[string]string)
   195  	for _, key := range keys {
   196  		m[key] = os.Getenv(key)
   197  	}
   198  
   199  	return func() {
   200  		for _, key := range keys {
   201  			os.Setenv(key, m[key])
   202  		}
   203  	}
   204  }