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.

125 lines
2.4 KiB

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