Last active
February 2, 2022 21:18
-
-
Save nyankichi820/cef786ded87bd494793f2897b357b9c1 to your computer and use it in GitHub Desktop.
nonce create math/rand vs crypt/rand
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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