random.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. // Package rand implements functions similar to math/rand in the standard
  7. // library, but on top of a secure random number generator.
  8. package rand
  9. import (
  10. cryptoRand "crypto/rand"
  11. mathRand "math/rand"
  12. "reflect"
  13. )
  14. // Reader is the standard crypto/rand.Reader, re-exported for convenience
  15. var Reader = cryptoRand.Reader
  16. // randomCharset contains the characters that can make up a rand.String().
  17. const randomCharset = "2345679abcdefghijkmnopqrstuvwxyzACDEFGHJKLMNPQRSTUVWXYZ"
  18. var (
  19. // defaultSecureSource is a concurrency safe math/rand.Source with a
  20. // cryptographically sound base.
  21. defaultSecureSource = newSecureSource()
  22. // defaultSecureRand is a math/rand.Rand based on the secure source.
  23. defaultSecureRand = mathRand.New(defaultSecureSource)
  24. )
  25. // String returns a strongly random string of characters (taken from
  26. // randomCharset) of the specified length. The returned string contains ~5.8
  27. // bits of entropy per character, due to the character set used.
  28. func String(l int) string {
  29. bs := make([]byte, l)
  30. for i := range bs {
  31. bs[i] = randomCharset[defaultSecureRand.Intn(len(randomCharset))]
  32. }
  33. return string(bs)
  34. }
  35. // Int63 returns a strongly random int63.
  36. func Int63() int64 {
  37. return defaultSecureSource.Int63()
  38. }
  39. // Int64 returns a strongly random int64.
  40. func Int64() int64 {
  41. return int64(defaultSecureSource.Uint64())
  42. }
  43. // Intn returns, as an int, a non-negative strongly random number in [0,n).
  44. // It panics if n <= 0.
  45. func Intn(n int) int {
  46. return defaultSecureRand.Intn(n)
  47. }
  48. // Shuffle the order of elements in slice.
  49. func Shuffle(slice interface{}) {
  50. rv := reflect.ValueOf(slice)
  51. swap := reflect.Swapper(slice)
  52. length := rv.Len()
  53. if length < 2 {
  54. return
  55. }
  56. defaultSecureRand.Shuffle(length, swap)
  57. }