all repos — captcha @ 26f056818c71476bfce1510edec3f1508d4c624e

Go package captcha implements generation and verification of image and audio CAPTCHAs.

random.go (view raw)

 1// Copyright 2011 Dmitry Chestnykh. All rights reserved.
 2// Use of this source code is governed by a MIT-style
 3// license that can be found in the LICENSE file.
 4
 5package captcha
 6
 7import (
 8	"crypto/rand"
 9	"io"
10)
11
12// idLen is a length of captcha id string.
13const idLen = 20
14
15// idChars are characters allowed in captcha id.
16var idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
17
18// RandomDigits returns a byte slice of the given length containing
19// pseudorandom numbers in range 0-9. The slice can be used as a captcha
20// solution.
21func RandomDigits(length int) []byte {
22	return randomBytesMod(length, 10)
23}
24
25// randomBytes returns a byte slice of the given length read from CSPRNG.
26func randomBytes(length int) (b []byte) {
27	b = make([]byte, length)
28	if _, err := io.ReadFull(rand.Reader, b); err != nil {
29		panic("captcha: error reading random source: " + err.Error())
30	}
31	return
32}
33
34// randomBytesMod returns a byte slice of the given length, where each byte is
35// a random number modulo mod.
36func randomBytesMod(length int, mod byte) (b []byte) {
37	b = make([]byte, length)
38	maxrb := byte(256 - (256 % int(mod)))
39	i := 0
40	for {
41		r := randomBytes(length + (length / 4))
42		for _, c := range r {
43			if c >= maxrb {
44				// Skip this number to avoid modulo bias.
45				continue
46			}
47			b[i] = c % mod
48			i++
49			if i == length {
50				return
51			}
52		}
53	}
54	panic("unreachable")
55}
56
57// randomId returns a new random id string.
58func randomId() string {
59	b := randomBytesMod(idLen, byte(len(idChars)))
60	for i, c := range b {
61		b[i] = idChars[c]
62	}
63	return string(b)
64}
65
66var prng = &siprng{}
67
68// randIntn returns a pseudorandom non-negative int in range [0, n).
69func randIntn(n int) int {
70	return prng.Intn(n)
71}
72
73// randInt returns a pseudorandom int in range [from, to].
74func randInt(from, to int) int {
75	return prng.Intn(to+1-from) + from
76}
77
78// randFloat returns a pseudorandom float64 in range [from, to].
79func randFloat(from, to float64) float64 {
80	return (to-from)*prng.Float64() + from
81}