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.

121 lines
2.4 KiB

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