random.go (view raw)
1package captcha
2
3import (
4 crand "crypto/rand"
5 "io"
6 "rand"
7 "time"
8)
9
10// idLen is a length of captcha id string.
11const idLen = 20
12
13// idChars are characters allowed in captcha id.
14var idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
15
16func init() {
17 rand.Seed(time.Nanoseconds())
18}
19
20// RandomDigits returns a byte slice of the given length containing
21// pseudorandom numbers in range 0-9. The slice can be used as a captcha
22// solution.
23func RandomDigits(length int) (b []byte) {
24 b = randomBytes(length)
25 for i := range b {
26 b[i] %= 10
27 }
28 return
29}
30
31// randomBytes returns a byte slice of the given length read from CSPRNG.
32func randomBytes(length int) (b []byte) {
33 b = make([]byte, length)
34 if _, err := io.ReadFull(crand.Reader, b); err != nil {
35 panic("error reading random source: " + err.String())
36 }
37 return
38}
39
40// randomId returns a new random id string.
41func randomId() string {
42 b := randomBytes(idLen)
43 alen := byte(len(idChars))
44 for i, c := range b {
45 b[i] = idChars[c%alen]
46 }
47 return string(b)
48}
49
50// rnd returns a non-crypto pseudorandom int in range [from, to].
51func rnd(from, to int) int {
52 return rand.Intn(to+1-from) + from
53}
54
55// rndf returns a non-crypto pseudorandom float64 in range [from, to].
56func rndf(from, to float64) float64 {
57 return (to-from)*rand.Float64() + from
58}