random.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. "io"
  11. mathRand "math/rand"
  12. "reflect"
  13. "strings"
  14. )
  15. // Reader is the standard crypto/rand.Reader with added buffering.
  16. var Reader = defaultSecureSource
  17. func Read(p []byte) (int, error) {
  18. return io.ReadFull(defaultSecureSource, p)
  19. }
  20. // randomCharset contains the characters that can make up a rand.String().
  21. const randomCharset = "2345679abcdefghijkmnopqrstuvwxyzACDEFGHJKLMNPQRSTUVWXYZ"
  22. var (
  23. // defaultSecureSource is a concurrency-safe, cryptographically secure
  24. // math/rand.Source.
  25. defaultSecureSource = newSecureSource()
  26. // defaultSecureRand is a math/rand.Rand based on the secure source.
  27. defaultSecureRand = mathRand.New(defaultSecureSource)
  28. )
  29. // String returns a cryptographically secure random string of characters
  30. // (taken from randomCharset) of the specified length. The returned string
  31. // contains ~5.8 bits of entropy per character, due to the character set used.
  32. func String(l int) string {
  33. var sb strings.Builder
  34. sb.Grow(l)
  35. for i := 0; i < l; i++ {
  36. sb.WriteByte(randomCharset[defaultSecureRand.Intn(len(randomCharset))])
  37. }
  38. return sb.String()
  39. }
  40. // Int63 returns a cryptographically secure random int63.
  41. func Int63() int64 {
  42. return defaultSecureSource.Int63()
  43. }
  44. // Uint64 returns a cryptographically secure strongly random uint64.
  45. func Uint64() uint64 {
  46. return defaultSecureSource.Uint64()
  47. }
  48. // Intn returns, as an int, a cryptographically secure non-negative
  49. // random number in [0,n). It panics if n <= 0.
  50. func Intn(n int) int {
  51. return defaultSecureRand.Intn(n)
  52. }
  53. // Shuffle the order of elements in slice.
  54. func Shuffle(slice interface{}) {
  55. rv := reflect.ValueOf(slice)
  56. swap := reflect.Swapper(slice)
  57. length := rv.Len()
  58. if length < 2 {
  59. return
  60. }
  61. defaultSecureRand.Shuffle(length, swap)
  62. }