Skip to content

Instantly share code, notes, and snippets.

@nyankichi820
Last active February 2, 2022 21:18
Show Gist options
  • Save nyankichi820/cef786ded87bd494793f2897b357b9c1 to your computer and use it in GitHub Desktop.
Save nyankichi820/cef786ded87bd494793f2897b357b9c1 to your computer and use it in GitHub Desktop.
nonce create math/rand vs crypt/rand
package main
import (
"encoding/binary"
"fmt"
"math/rand"
crand "crypto/rand"
"sync"
"time"
)
var (
rsLetterIdxBits = 6
rsLetterIdxMask int64 = 1<<rsLetterIdxBits - 1
rsLetterIdxMax = 63 / rsLetterIdxBits
randSrc = rand.NewSource(time.Now().UnixNano())
)
func main() {
check := map[string]bool{}
for i := 0; i < 100; i++ {
gen(check)
}
}
func gen(check map[string]bool) {
var mu sync.RWMutex
var wg sync.WaitGroup
sem := make(chan struct{}, 4)
for i := 0; i < 13; i++ {
wg.Add(1)
go func(index int) {
sem <- struct{}{}
defer wg.Done()
defer mu.Unlock()
defer func() { <-sem }()
now := NowMsec()
nonce := GenerateNonce(now)
mu.Lock()
if check[nonce] {
fmt.Printf("already create %d %v %v\n", index, now, nonce)
}
// fmt.Printf("%d %v %v\n", index, now, nonce)
check[nonce] = true
}(i)
}
wg.Wait()
}
func NowMsec() int64 {
return time.Now().UnixNano() / 1000000
}
func GenerateNonce(timestampMsec int64) string {
// TODO The same nonce can’t be reused per service-api-key within 20 seconds.
// An error is returned when the nonce of the successful request is reused within 20 seconds.
// math/rand
return randString(8)
// crypt/rand
//return crandString(8)
}
func randInt() int64 {
return Int63()
}
func Uint64() uint64 {
b := [8]byte{}
ct, _ := crand.Read(b[:])
return binary.BigEndian.Uint64(b[:ct])
}
// Int63 method generates a random number in the range [0, 1<<63).
func Int63() int64 {
return (int64)(Uint64() >> 1)
}
func randString(l int) string {
rsLetters := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, l)
cache, remain := randSrc.Int63(), rsLetterIdxMax
for i := l - 1; i >= 0; {
if remain == 0 {
cache, remain = randSrc.Int63(), rsLetterIdxMax
}
idx := int(cache & rsLetterIdxMask)
if idx < len(rsLetters) {
b[i] = rsLetters[idx]
i--
}
cache >>= rsLetterIdxBits
remain--
}
return string(b)
}
func crandString(l int) string {
rsLetters := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, l)
cache, remain := randInt(), rsLetterIdxMax
for i := l - 1; i >= 0; {
if remain == 0 {
cache, remain = randInt(), rsLetterIdxMax
}
idx := int(cache & rsLetterIdxMask)
if idx < len(rsLetters) {
b[i] = rsLetters[idx]
i--
}
cache >>= rsLetterIdxBits
remain--
}
return string(b)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment