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.

145 lines
2.7 KiB

9 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 RandInt16() int16 {
  56. return int16(rand.Uint32() & (1<<16 - 1))
  57. }
  58. func RandInt32() int32 {
  59. return int32(rand.Uint32())
  60. }
  61. func RandInt64() int64 {
  62. return int64(rand.Uint32())<<32 + int64(rand.Uint32())
  63. }
  64. func RandInt() int {
  65. return rand.Int()
  66. }
  67. // Distributed pseudo-exponentially to test for various cases
  68. func RandUint16Exp() uint16 {
  69. bits := rand.Uint32() % 16
  70. if bits == 0 {
  71. return 0
  72. }
  73. n := uint16(1 << (bits - 1))
  74. n += uint16(rand.Int31()) & ((1 << (bits - 1)) - 1)
  75. return n
  76. }
  77. // Distributed pseudo-exponentially to test for various cases
  78. func RandUint32Exp() uint32 {
  79. bits := rand.Uint32() % 32
  80. if bits == 0 {
  81. return 0
  82. }
  83. n := uint32(1 << (bits - 1))
  84. n += uint32(rand.Int31()) & ((1 << (bits - 1)) - 1)
  85. return n
  86. }
  87. // Distributed pseudo-exponentially to test for various cases
  88. func RandUint64Exp() uint64 {
  89. bits := rand.Uint32() % 64
  90. if bits == 0 {
  91. return 0
  92. }
  93. n := uint64(1 << (bits - 1))
  94. n += uint64(rand.Int63()) & ((1 << (bits - 1)) - 1)
  95. return n
  96. }
  97. func RandFloat32() float32 {
  98. return rand.Float32()
  99. }
  100. func RandTime() time.Time {
  101. return time.Unix(int64(RandUint64Exp()), 0)
  102. }
  103. func RandBytes(n int) []byte {
  104. bs := make([]byte, n)
  105. for i := 0; i < n; i++ {
  106. bs[i] = byte(rand.Intn(256))
  107. }
  108. return bs
  109. }
  110. //-----------------------------------------------------------------------------
  111. // CRand* methods are crypto safe.
  112. func CRandBytes(numBytes int) []byte {
  113. b := make([]byte, numBytes)
  114. _, err := crand.Read(b)
  115. if err != nil {
  116. PanicCrisis(err)
  117. }
  118. return b
  119. }
  120. // RandHex(24) gives 96 bits of randomness, strong enough for most purposes.
  121. func CRandHex(numDigits int) string {
  122. return hex.EncodeToString(CRandBytes(numDigits / 2))
  123. }