auth.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package mtproto
  2. import (
  3. "crypto/rand"
  4. "crypto/sha256"
  5. "io"
  6. "sync"
  7. "v2ray.com/core/common"
  8. )
  9. const (
  10. HeaderSize = 64
  11. )
  12. type Authentication struct {
  13. Header [HeaderSize]byte
  14. DecodingKey [32]byte
  15. EncodingKey [32]byte
  16. DecodingNonce [16]byte
  17. EncodingNonce [16]byte
  18. }
  19. func (a *Authentication) DataCenterID() uint16 {
  20. return (uint16(a.Header[61]) << 8) | uint16(a.Header[60])
  21. }
  22. func (a *Authentication) ApplySecret(b []byte) {
  23. a.DecodingKey = sha256.Sum256(append(a.DecodingKey[:], b...))
  24. a.EncodingKey = sha256.Sum256(append(a.EncodingKey[:], b...))
  25. }
  26. func generateRandomBytes(random []byte) {
  27. for {
  28. common.Must2(rand.Read(random[:]))
  29. if random[0] == 0xef {
  30. continue
  31. }
  32. val := (uint32(random[3]) << 24) | (uint32(random[2]) << 16) | (uint32(random[1]) << 8) | uint32(random[0])
  33. if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee {
  34. continue
  35. }
  36. if 0x00000000 == (uint32(random[7])<<24)|(uint32(random[6])<<16)|(uint32(random[5])<<8)|uint32(random[4]) {
  37. continue
  38. }
  39. return
  40. }
  41. }
  42. func NewAuthentication() *Authentication {
  43. auth := getAuthenticationObject()
  44. random := auth.Header[:]
  45. generateRandomBytes(random)
  46. copy(auth.EncodingKey[:], random[8:])
  47. copy(auth.EncodingNonce[:], random[8+32:])
  48. keyivInverse := Inverse(random[8 : 8+32+16])
  49. copy(auth.DecodingKey[:], keyivInverse)
  50. copy(auth.DecodingNonce[:], keyivInverse[32:])
  51. return auth
  52. }
  53. func ReadAuthentication(reader io.Reader) (*Authentication, error) {
  54. auth := getAuthenticationObject()
  55. if _, err := io.ReadFull(reader, auth.Header[:]); err != nil {
  56. putAuthenticationObject(auth)
  57. return nil, err
  58. }
  59. copy(auth.DecodingKey[:], auth.Header[8:])
  60. copy(auth.DecodingNonce[:], auth.Header[8+32:])
  61. keyivInverse := Inverse(auth.Header[8 : 8+32+16])
  62. copy(auth.EncodingKey[:], keyivInverse)
  63. copy(auth.EncodingNonce[:], keyivInverse[32:])
  64. return auth, nil
  65. }
  66. // Inverse returns a new byte array. It is a sequence of bytes when the input is read from end to beginning.Inverse
  67. // Visible for testing only.
  68. func Inverse(b []byte) []byte {
  69. lenb := len(b)
  70. b2 := make([]byte, lenb)
  71. for i, v := range b {
  72. b2[lenb-i-1] = v
  73. }
  74. return b2
  75. }
  76. var (
  77. authPool = sync.Pool{
  78. New: func() interface{} {
  79. return new(Authentication)
  80. },
  81. }
  82. )
  83. func getAuthenticationObject() *Authentication {
  84. return authPool.Get().(*Authentication)
  85. }
  86. func putAuthenticationObject(auth *Authentication) {
  87. authPool.Put(auth)
  88. }