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.

217 lines
4.4 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package common
  2. import (
  3. crand "crypto/rand"
  4. mrand "math/rand"
  5. "sync"
  6. "time"
  7. )
  8. const (
  9. strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
  10. )
  11. // pseudo random number generator.
  12. // seeded with OS randomness (crand)
  13. var prng struct {
  14. sync.Mutex
  15. *mrand.Rand
  16. }
  17. func reset() {
  18. b := cRandBytes(8)
  19. var seed uint64
  20. for i := 0; i < 8; i++ {
  21. seed |= uint64(b[i])
  22. seed <<= 8
  23. }
  24. prng.Lock()
  25. prng.Rand = mrand.New(mrand.NewSource(int64(seed)))
  26. prng.Unlock()
  27. }
  28. func init() {
  29. reset()
  30. }
  31. // Constructs an alphanumeric string of given length.
  32. // It is not safe for cryptographic usage.
  33. func RandStr(length int) string {
  34. chars := []byte{}
  35. MAIN_LOOP:
  36. for {
  37. val := prng.Int63()
  38. for i := 0; i < 10; i++ {
  39. v := int(val & 0x3f) // rightmost 6 bits
  40. if v >= 62 { // only 62 characters in strChars
  41. val >>= 6
  42. continue
  43. } else {
  44. chars = append(chars, strChars[v])
  45. if len(chars) == length {
  46. break MAIN_LOOP
  47. }
  48. val >>= 6
  49. }
  50. }
  51. }
  52. return string(chars)
  53. }
  54. // It is not safe for cryptographic usage.
  55. func RandUint16() uint16 {
  56. return uint16(RandUint32() & (1<<16 - 1))
  57. }
  58. // It is not safe for cryptographic usage.
  59. func RandUint32() uint32 {
  60. prng.Lock()
  61. u32 := prng.Uint32()
  62. prng.Unlock()
  63. return u32
  64. }
  65. // It is not safe for cryptographic usage.
  66. func RandUint64() uint64 {
  67. return uint64(RandUint32())<<32 + uint64(RandUint32())
  68. }
  69. // It is not safe for cryptographic usage.
  70. func RandUint() uint {
  71. prng.Lock()
  72. i := prng.Int()
  73. prng.Unlock()
  74. return uint(i)
  75. }
  76. // It is not safe for cryptographic usage.
  77. func RandInt16() int16 {
  78. return int16(RandUint32() & (1<<16 - 1))
  79. }
  80. // It is not safe for cryptographic usage.
  81. func RandInt32() int32 {
  82. return int32(RandUint32())
  83. }
  84. // It is not safe for cryptographic usage.
  85. func RandInt64() int64 {
  86. return int64(RandUint64())
  87. }
  88. // It is not safe for cryptographic usage.
  89. func RandInt() int {
  90. prng.Lock()
  91. i := prng.Int()
  92. prng.Unlock()
  93. return i
  94. }
  95. // It is not safe for cryptographic usage.
  96. func RandInt31() int32 {
  97. prng.Lock()
  98. i31 := prng.Int31()
  99. prng.Unlock()
  100. return i31
  101. }
  102. // It is not safe for cryptographic usage.
  103. func RandInt63() int64 {
  104. prng.Lock()
  105. i63 := prng.Int63()
  106. prng.Unlock()
  107. return i63
  108. }
  109. // Distributed pseudo-exponentially to test for various cases
  110. // It is not safe for cryptographic usage.
  111. func RandUint16Exp() uint16 {
  112. bits := RandUint32() % 16
  113. if bits == 0 {
  114. return 0
  115. }
  116. n := uint16(1 << (bits - 1))
  117. n += uint16(RandInt31()) & ((1 << (bits - 1)) - 1)
  118. return n
  119. }
  120. // Distributed pseudo-exponentially to test for various cases
  121. // It is not safe for cryptographic usage.
  122. func RandUint32Exp() uint32 {
  123. bits := RandUint32() % 32
  124. if bits == 0 {
  125. return 0
  126. }
  127. n := uint32(1 << (bits - 1))
  128. n += uint32(RandInt31()) & ((1 << (bits - 1)) - 1)
  129. return n
  130. }
  131. // Distributed pseudo-exponentially to test for various cases
  132. // It is not safe for cryptographic usage.
  133. func RandUint64Exp() uint64 {
  134. bits := RandUint32() % 64
  135. if bits == 0 {
  136. return 0
  137. }
  138. n := uint64(1 << (bits - 1))
  139. n += uint64(RandInt63()) & ((1 << (bits - 1)) - 1)
  140. return n
  141. }
  142. // It is not safe for cryptographic usage.
  143. func RandFloat32() float32 {
  144. prng.Lock()
  145. f32 := prng.Float32()
  146. prng.Unlock()
  147. return f32
  148. }
  149. // It is not safe for cryptographic usage.
  150. func RandTime() time.Time {
  151. return time.Unix(int64(RandUint64Exp()), 0)
  152. }
  153. // RandBytes returns n random bytes from the OS's source of entropy ie. via crypto/rand.
  154. // It is not safe for cryptographic usage.
  155. func RandBytes(n int) []byte {
  156. // cRandBytes isn't guaranteed to be fast so instead
  157. // use random bytes generated from the internal PRNG
  158. bs := make([]byte, n)
  159. for i := 0; i < len(bs); i++ {
  160. bs[i] = byte(RandInt() & 0xFF)
  161. }
  162. return bs
  163. }
  164. // RandIntn returns, as an int, a non-negative pseudo-random number in [0, n).
  165. // It panics if n <= 0.
  166. // It is not safe for cryptographic usage.
  167. func RandIntn(n int) int {
  168. prng.Lock()
  169. i := prng.Intn(n)
  170. prng.Unlock()
  171. return i
  172. }
  173. // RandPerm returns a pseudo-random permutation of n integers in [0, n).
  174. // It is not safe for cryptographic usage.
  175. func RandPerm(n int) []int {
  176. prng.Lock()
  177. perm := prng.Perm(n)
  178. prng.Unlock()
  179. return perm
  180. }
  181. // NOTE: This relies on the os's random number generator.
  182. // For real security, we should salt that with some seed.
  183. // See github.com/tendermint/go-crypto for a more secure reader.
  184. func cRandBytes(numBytes int) []byte {
  185. b := make([]byte, numBytes)
  186. _, err := crand.Read(b)
  187. if err != nil {
  188. PanicCrisis(err)
  189. }
  190. return b
  191. }