You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
2.5 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
  1. package common
  2. import (
  3. crand "crypto/rand"
  4. "encoding/hex"
  5. "math/rand"
  6. "time"
  7. )
  8. const (
  9. strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
  10. )
  11. func init() {
  12. // Seed math/rand with "secure" int64
  13. b := CRandBytes(8)
  14. var seed uint64
  15. for i := 0; i < 8; i++ {
  16. seed |= uint64(b[i])
  17. seed <<= 8
  18. }
  19. rand.Seed(int64(seed))
  20. }
  21. // Constructs an alphanumeric string of given length.
  22. func RandStr(length int) string {
  23. chars := []byte{}
  24. MAIN_LOOP:
  25. for {
  26. val := rand.Int63()
  27. for i := 0; i < 10; i++ {
  28. v := int(val & 0x3f) // rightmost 6 bits
  29. if v >= 62 { // only 62 characters in strChars
  30. val >>= 6
  31. continue
  32. } else {
  33. chars = append(chars, strChars[v])
  34. if len(chars) == length {
  35. break MAIN_LOOP
  36. }
  37. val >>= 6
  38. }
  39. }
  40. }
  41. return string(chars)
  42. }
  43. func RandUint16() uint16 {
  44. return uint16(rand.Uint32() & (1<<16 - 1))
  45. }
  46. func RandUint32() uint32 {
  47. return rand.Uint32()
  48. }
  49. func RandUint64() uint64 {
  50. return uint64(rand.Uint32())<<32 + uint64(rand.Uint32())
  51. }
  52. func RandUint() uint {
  53. return uint(rand.Int())
  54. }
  55. func RandInt() int {
  56. return rand.Int()
  57. }
  58. // Distributed pseudo-exponentially to test for various cases
  59. func RandUint16Exp() uint16 {
  60. bits := rand.Uint32() % 16
  61. if bits == 0 {
  62. return 0
  63. }
  64. n := uint16(1 << (bits - 1))
  65. n += uint16(rand.Int31()) & ((1 << (bits - 1)) - 1)
  66. return n
  67. }
  68. // Distributed pseudo-exponentially to test for various cases
  69. func RandUint32Exp() uint32 {
  70. bits := rand.Uint32() % 32
  71. if bits == 0 {
  72. return 0
  73. }
  74. n := uint32(1 << (bits - 1))
  75. n += uint32(rand.Int31()) & ((1 << (bits - 1)) - 1)
  76. return n
  77. }
  78. // Distributed pseudo-exponentially to test for various cases
  79. func RandUint64Exp() uint64 {
  80. bits := rand.Uint32() % 64
  81. if bits == 0 {
  82. return 0
  83. }
  84. n := uint64(1 << (bits - 1))
  85. n += uint64(rand.Int63()) & ((1 << (bits - 1)) - 1)
  86. return n
  87. }
  88. func RandFloat32() float32 {
  89. return rand.Float32()
  90. }
  91. func RandTime() time.Time {
  92. return time.Unix(int64(RandUint64Exp()), 0)
  93. }
  94. func RandBytes(n int) []byte {
  95. bs := make([]byte, n)
  96. for i := 0; i < n; i++ {
  97. bs[i] = byte(rand.Intn(256))
  98. }
  99. return bs
  100. }
  101. //-----------------------------------------------------------------------------
  102. // CRand* methods are crypto safe.
  103. func CRandBytes(numBytes int) []byte {
  104. b := make([]byte, numBytes)
  105. _, err := crand.Read(b)
  106. if err != nil {
  107. panic(err)
  108. }
  109. return b
  110. }
  111. // RandHex(24) gives 96 bits of randomness, strong enough for most purposes.
  112. func CRandHex(numDigits int) string {
  113. return hex.EncodeToString(CRandBytes(numDigits / 2))
  114. }