random.go 1.5 KB

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