Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
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.

secret.go 2.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package mtglib
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "encoding/hex"
  6. "fmt"
  7. )
  8. const (
  9. SecretKeyLength = 16
  10. secretFakeTLSFirstByte byte = 0xee
  11. )
  12. var secretEmptyKey [SecretKeyLength]byte
  13. type Secret struct {
  14. Key [SecretKeyLength]byte
  15. Host string
  16. }
  17. func (s Secret) MarshalText() ([]byte, error) {
  18. if s.Valid() {
  19. return []byte(s.String()), nil
  20. }
  21. return nil, nil
  22. }
  23. func (s *Secret) UnmarshalText(data []byte) error {
  24. text := string(data)
  25. if text == "" {
  26. return ErrSecretEmpty
  27. }
  28. decoded, err := hex.DecodeString(text)
  29. if err != nil {
  30. decoded, err = base64.RawURLEncoding.DecodeString(text)
  31. }
  32. if err != nil {
  33. return fmt.Errorf("incorrect secret format: %w", err)
  34. }
  35. if len(decoded) < 2 { // nolint: gomnd // we need at least 1 byte here
  36. return fmt.Errorf("secret is truncated, length=%d", len(decoded))
  37. }
  38. if decoded[0] != secretFakeTLSFirstByte {
  39. return fmt.Errorf("incorrect first byte of secret: %#x", decoded[0])
  40. }
  41. decoded = decoded[1:]
  42. if len(decoded) < SecretKeyLength {
  43. return fmt.Errorf("secret has incorrect length %d", len(decoded))
  44. }
  45. copy(s.Key[:], decoded[:SecretKeyLength])
  46. s.Host = string(decoded[SecretKeyLength:])
  47. if s.Host == "" {
  48. return fmt.Errorf("hostname cannot be empty: %s", text)
  49. }
  50. return nil
  51. }
  52. func (s Secret) Valid() bool {
  53. return s.Key != secretEmptyKey && s.Host != ""
  54. }
  55. func (s Secret) String() string {
  56. return s.Base64()
  57. }
  58. func (s Secret) Base64() string {
  59. return base64.RawURLEncoding.EncodeToString(s.makeBytes())
  60. }
  61. func (s Secret) Hex() string {
  62. return hex.EncodeToString(s.makeBytes())
  63. }
  64. func (s *Secret) makeBytes() []byte {
  65. data := append([]byte{secretFakeTLSFirstByte}, s.Key[:]...)
  66. data = append(data, s.Host...)
  67. return data
  68. }
  69. func GenerateSecret(hostname string) Secret {
  70. s := Secret{
  71. Host: hostname,
  72. }
  73. if _, err := rand.Read(s.Key[:]); err != nil {
  74. panic(err)
  75. }
  76. return s
  77. }
  78. func ParseSecret(secret string) (Secret, error) {
  79. s := Secret{}
  80. return s, s.UnmarshalText([]byte(secret))
  81. }