random.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Package random provides utilities for generating random strings and numbers.
  2. package random
  3. import (
  4. "crypto/rand"
  5. "encoding/base64"
  6. "math/big"
  7. )
  8. var (
  9. numSeq [10]rune
  10. lowerSeq [26]rune
  11. upperSeq [26]rune
  12. numLowerSeq [36]rune
  13. numUpperSeq [36]rune
  14. allSeq [62]rune
  15. )
  16. // init initializes the character sequences used for random string generation.
  17. // It sets up arrays for numbers, lowercase letters, uppercase letters, and combinations.
  18. func init() {
  19. for i := range 10 {
  20. numSeq[i] = rune('0' + i)
  21. }
  22. for i := range 26 {
  23. lowerSeq[i] = rune('a' + i)
  24. upperSeq[i] = rune('A' + i)
  25. }
  26. copy(numLowerSeq[:], numSeq[:])
  27. copy(numLowerSeq[len(numSeq):], lowerSeq[:])
  28. copy(numUpperSeq[:], numSeq[:])
  29. copy(numUpperSeq[len(numSeq):], upperSeq[:])
  30. copy(allSeq[:], numSeq[:])
  31. copy(allSeq[len(numSeq):], lowerSeq[:])
  32. copy(allSeq[len(numSeq)+len(lowerSeq):], upperSeq[:])
  33. }
  34. // Seq generates a random string of length n containing alphanumeric characters (numbers, lowercase and uppercase letters).
  35. func Seq(n int) string {
  36. runes := make([]rune, n)
  37. for i := range n {
  38. idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(allSeq))))
  39. if err != nil {
  40. panic("crypto/rand failed: " + err.Error())
  41. }
  42. runes[i] = allSeq[idx.Int64()]
  43. }
  44. return string(runes)
  45. }
  46. // Num generates a random integer between 0 and n-1.
  47. func Num(n int) int {
  48. bn := big.NewInt(int64(n))
  49. r, err := rand.Int(rand.Reader, bn)
  50. if err != nil {
  51. panic("crypto/rand failed: " + err.Error())
  52. }
  53. return int(r.Int64())
  54. }
  55. // Base64Bytes returns n cryptographically-random bytes encoded as standard
  56. // base64 (with padding). Used for ss2022 keys, which xray expects as a
  57. // base64-encoded key of a specific byte length per cipher.
  58. func Base64Bytes(n int) string {
  59. b := make([]byte, n)
  60. if _, err := rand.Read(b); err != nil {
  61. panic("crypto/rand failed: " + err.Error())
  62. }
  63. return base64.StdEncoding.EncodeToString(b)
  64. }