mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-02 00:11:56 +03:00
Add documentation for a secret
This commit is contained in:
+40
-1
@@ -11,11 +11,43 @@ const secretFakeTLSFirstByte byte = 0xee
|
|||||||
|
|
||||||
var secretEmptyKey [SecretKeyLength]byte
|
var secretEmptyKey [SecretKeyLength]byte
|
||||||
|
|
||||||
|
// Secret is a data structure that presents a secret.
|
||||||
|
//
|
||||||
|
// Telegram secret is not a simple string like
|
||||||
|
// "ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d".
|
||||||
|
// Actually, this is a serialized datastructure of 2 parts: key and host.
|
||||||
|
//
|
||||||
|
// ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d
|
||||||
|
// |-|-------------------------------|-------------------------------------------
|
||||||
|
// p key hostname
|
||||||
|
//
|
||||||
|
// Serialized secret starts with 'ee'. Actually, in the past we also had
|
||||||
|
// 'dd' secrets and prefixless ones. But this is history. Currently,
|
||||||
|
// we do have only 'ee' secrets which mean faketls + protection from
|
||||||
|
// statistical attacks on a length. 'ee' is a byte 238 (0xee).
|
||||||
|
//
|
||||||
|
// After that, we have 16 bytes of the key. This is a random generated
|
||||||
|
// secret data of the proxy and this data is used to derive
|
||||||
|
// authentication schemas. These secrets are mixed into hmacs and sha256
|
||||||
|
// checksums which are used to build AEAD ciphers for obfuscated2
|
||||||
|
// protocol and ensure faketls handshake.
|
||||||
|
//
|
||||||
|
// Host is a domain fronting hostname in latin1 (ASCII) encoding. This
|
||||||
|
// hostname should be used for SNI in faketls and MTG verifies it. Also,
|
||||||
|
// this is when mtg gets about a domain fronting hostname.
|
||||||
|
//
|
||||||
|
// Secrets can be serialized into 2 forms: hex and base64. If
|
||||||
|
// you decode both forms into bytes, you'll get the same byte array.
|
||||||
|
// Telegram clients nowadays accept all forms.
|
||||||
type Secret struct {
|
type Secret struct {
|
||||||
Key [SecretKeyLength]byte
|
// Key is a set of bytes used for traffic authentication.
|
||||||
|
Key [SecretKeyLength]byte
|
||||||
|
|
||||||
|
// Host is a domain fronting hostname.
|
||||||
Host string
|
Host string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalText is to support text.Marshaller interface.
|
||||||
func (s Secret) MarshalText() ([]byte, error) {
|
func (s Secret) MarshalText() ([]byte, error) {
|
||||||
if s.Valid() {
|
if s.Valid() {
|
||||||
return []byte(s.String()), nil
|
return []byte(s.String()), nil
|
||||||
@@ -24,6 +56,7 @@ func (s Secret) MarshalText() ([]byte, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalText is to support text.Unmarshaller interface.
|
||||||
func (s *Secret) UnmarshalText(data []byte) error {
|
func (s *Secret) UnmarshalText(data []byte) error {
|
||||||
text := string(data)
|
text := string(data)
|
||||||
if text == "" {
|
if text == "" {
|
||||||
@@ -62,18 +95,22 @@ func (s *Secret) UnmarshalText(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Valid checks if this secret is valid and can be used in proxy.
|
||||||
func (s Secret) Valid() bool {
|
func (s Secret) Valid() bool {
|
||||||
return s.Key != secretEmptyKey && s.Host != ""
|
return s.Key != secretEmptyKey && s.Host != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String is to support fmt.Stringer interface.
|
||||||
func (s Secret) String() string {
|
func (s Secret) String() string {
|
||||||
return s.Base64()
|
return s.Base64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Base64 returns a base64-encoded form of this secret.
|
||||||
func (s Secret) Base64() string {
|
func (s Secret) Base64() string {
|
||||||
return base64.RawURLEncoding.EncodeToString(s.makeBytes())
|
return base64.RawURLEncoding.EncodeToString(s.makeBytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hex returns a hex-encoded form of this secret (ee-secret).
|
||||||
func (s Secret) Hex() string {
|
func (s Secret) Hex() string {
|
||||||
return hex.EncodeToString(s.makeBytes())
|
return hex.EncodeToString(s.makeBytes())
|
||||||
}
|
}
|
||||||
@@ -85,6 +122,7 @@ func (s *Secret) makeBytes() []byte {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateSecret makes a new secret with a given hostname.
|
||||||
func GenerateSecret(hostname string) Secret {
|
func GenerateSecret(hostname string) Secret {
|
||||||
s := Secret{
|
s := Secret{
|
||||||
Host: hostname,
|
Host: hostname,
|
||||||
@@ -97,6 +135,7 @@ func GenerateSecret(hostname string) Secret {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseSecret parses a secret (both hex and base64 forms).
|
||||||
func ParseSecret(secret string) (Secret, error) {
|
func ParseSecret(secret string) (Secret, error) {
|
||||||
s := Secret{}
|
s := Secret{}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user