Skip to content

Commit

Permalink
Socks(4,5) Proxy support,MTProto 2.0 Hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
AmarnathCJD committed Oct 21, 2022
1 parent 4c6044e commit a9f35a2
Show file tree
Hide file tree
Showing 23 changed files with 400 additions and 272 deletions.
2 changes: 1 addition & 1 deletion errors.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2022 RoseLoverX

package mtproto
package gogram

import (
"fmt"
Expand Down
2 changes: 1 addition & 1 deletion handshake.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2022 RoseLoverX

package mtproto
package gogram

import (
"bytes"
Expand Down
81 changes: 62 additions & 19 deletions internal/aes_ige/aes.go
Original file line number Diff line number Diff line change
@@ -1,49 +1,88 @@
// Copyright (c) 2022 RoseLoverX
// Copyright (c) 2022,RoseLoverX

package ige

import (
"bytes"
"crypto/aes"
"crypto/rand"
"crypto/sha256"
"math/big"

utils "github.com/amarnathcjd/gogram/internal/encoding/tl"
"github.com/amarnathcjd/gogram/internal/utils"
)

type AesBlock [aes.BlockSize]byte
type AesKV [32]byte
type AesIgeBlock [48]byte

func MessageKey(msg []byte) []byte {
return utils.Sha1(string(msg))[4:20]
func MessageKey(authKey, msgPadded []byte, decode bool) []byte {
var x int
if decode {
x = 8
} else {
x = 0
}

// `msg_key_large = SHA256 (substr (auth_key, 88+x, 32) + plaintext + random_padding);`
var msgKeyLarge [sha256.Size]byte
{
h := sha256.New()

substr := authKey[88+x:]
_, _ = h.Write(substr[:32])
_, _ = h.Write(msgPadded)

h.Sum(msgKeyLarge[:0])
}
r := make([]byte, 16)
// `msg_key = substr (msg_key_large, 8, 16);`
copy(r, msgKeyLarge[8:8+16])
return r
}

func Encrypt(msg, key []byte) ([]byte, error) {
msgKey := MessageKey(msg)
aesKey, aesIV := generateAESIGE(msgKey, key, false)
func Encrypt(msg, authKey []byte) (out, msgKey []byte, _ error) {
return encrypt(msg, authKey, false)
}

func encrypt(msg, authKey []byte, decode bool) (out, msgKey []byte, _ error) {
// СУДЯ ПО ВСЕМУ вообще не уверен, но это видимо паддинг для добива блока, чтоб он делился на 256 бит
data := make([]byte, len(msg)+((16-(len(msg)%16))&15))
copy(data, msg)
padding := 16 + (16-(len(msg)%16))&15
data := make([]byte, len(msg)+padding)
n := copy(data, msg)

// Fill padding using secure PRNG.
//
// See https://core.telegram.org/mtproto/description#encrypted-message-encrypted-data.
if _, err := rand.Read(data[n:]); err != nil {
return nil, nil, err
}

c, err := NewCipher(aesKey, aesIV)
msgKey = MessageKey(authKey, data, decode)
aesKey, aesIV := aesKeys(msgKey[:], authKey, decode)

c, err := NewCipher(aesKey[:], aesIV[:])
if err != nil {
return nil, err
return nil, nil, err
}

out := make([]byte, len(data))
out = make([]byte, len(data))
if err := c.doAES256IGEencrypt(data, out); err != nil {
return nil, err
return nil, nil, err
}

return out, nil
return out, msgKey, nil
}

// checkData это msgkey в понятиях мтпрото, нужно что бы проверить, успешно ли прошла расшифровка
func Decrypt(msg, key, checkData []byte) ([]byte, error) {
aesKey, aesIV := generateAESIGE(checkData, key, true)
func Decrypt(msg, authKey, checkData []byte) ([]byte, error) {
return decrypt(msg, authKey, checkData, true)
}

func decrypt(msg, authKey, msgKey []byte, decode bool) ([]byte, error) {
aesKey, aesIV := aesKeys(msgKey, authKey, decode)

c, err := NewCipher(aesKey, aesIV)
c, err := NewCipher(aesKey[:], aesIV[:])
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -77,7 +116,9 @@ func DecryptMessageWithTempKeys(msg []byte, nonceSecond, nonceServer *big.Int) [
key, iv := generateTempKeys(nonceSecond, nonceServer)
decodedWithHash := make([]byte, len(msg))
err := doAES256IGEdecrypt(msg, decodedWithHash, key, iv)
check(err)
if err != nil {
panic(err)
}

// decodedWithHash := SHA1(answer) + answer + (0-15 рандомных байт); длина должна делиться на 16;
decodedHash := decodedWithHash[:20]
Expand Down Expand Up @@ -111,7 +152,9 @@ func encryptMessageWithTempKeys(msg []byte, nonceSecond, nonceServer *big.Int) [

encodedWithHash := make([]byte, len(msg))
err := doAES256IGEencrypt(msg, encodedWithHash, key, iv)
check(err)
if err != nil {
panic(err)
}

return encodedWithHash
}
Expand Down
12 changes: 0 additions & 12 deletions internal/aes_ige/extra.go

This file was deleted.

148 changes: 37 additions & 111 deletions internal/aes_ige/ige_cipher.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Copyright (c) 2022 RoseLoverX
// Copyright (c) 2022,RoseLoverX

package ige

import (
"crypto/aes"
"crypto/cipher"
"fmt"
"crypto/sha256"

utils "github.com/amarnathcjd/gogram/internal/encoding/tl"
"github.com/amarnathcjd/gogram/internal/utils"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -48,9 +48,9 @@ func (c *Cipher) doAES256IGEencrypt(in, out []byte) error { //nolint:dupl пот
}

for i := 0; i < len(in); i += aes.BlockSize {
xor(c.x, in[i:i+aes.BlockSize])
utils.Xor(c.x, in[i:i+aes.BlockSize])
c.block.Encrypt(c.t, c.x)
xor(c.t, c.y)
utils.Xor(c.t, c.y)
c.x, c.y = c.t, in[i:i+aes.BlockSize]
copy(out[i:], c.t)
}
Expand All @@ -63,9 +63,9 @@ func (c *Cipher) doAES256IGEdecrypt(in, out []byte) error { //nolint:dupl пот
}

for i := 0; i < len(in); i += aes.BlockSize {
xor(c.y, in[i:i+aes.BlockSize])
utils.Xor(c.y, in[i:i+aes.BlockSize])
c.block.Decrypt(c.t, c.y)
xor(c.t, c.x)
utils.Xor(c.t, c.x)
c.y, c.x = c.t, in[i:i+aes.BlockSize]
copy(out[i:], c.t)
}
Expand All @@ -84,123 +84,49 @@ func isCorrectData(data []byte) error {

// --------------------------------------------------------------------------------------------------

// generateAESIGEv2 это переписанная функция generateAESIGE, которая выглядить чуточку более понятно.
func generateAESIGEv2(msgKey, authKey []byte, decode bool) (aesKey, aesIv []byte) { //nolint:deadcode wait for it
var (
kvBlock [2]AesKV
igeBlock [4]AesIgeBlock
)

aesKey = kvBlock[0][:]
aesIv = kvBlock[1][:]

tA := igeBlock[0][:]
tB := igeBlock[1][:]
tC := igeBlock[2][:]
tD := igeBlock[3][:]

func aesKeys(msgKey, authKey []byte, decode bool) (aesKey, aesIv [32]byte) {
var x int
if decode {
x = 8
} else {
x = 0
}

var (
step = 32
tAOffStart = x
tAOffEnd = tAOffStart + step

tBOffP0Start = tAOffEnd
tBOffP0End = tBOffP0Start + aes.BlockSize

tBOffP1Start = tAOffEnd + aes.BlockSize
tBOffP1End = tBOffP1Start + aes.BlockSize

tCOffStart = x + 64
tCOffEnd = tCOffStart + step

tDOffStart = x + 96
tDOffEnd = tDOffStart + step
)

tA = append(tA, msgKey...)
tA = append(tA, authKey[tAOffStart:tAOffEnd]...)

tB = append(tB, authKey[tBOffP0Start:tBOffP0End]...)
tB = append(tB, msgKey...)
tB = append(tB, authKey[tBOffP1Start:tBOffP1End]...)

tC = append(tC, authKey[tCOffStart:tCOffEnd]...)
tC = append(tC, msgKey...)

tD = append(tD, msgKey...)
tD = append(tD, authKey[tDOffStart:tDOffEnd]...)

sha1PartA := utils.Sha1Byte(tA)
sha1PartB := utils.Sha1Byte(tB)
sha1PartC := utils.Sha1Byte(tC)
sha1PartD := utils.Sha1Byte(tD)

aesKey = append(aesKey, sha1PartA[0:8]...)
aesKey = append(aesKey, sha1PartB[8:8+12]...)
aesKey = append(aesKey, sha1PartC[4:4+12]...)

aesIv = append(aesIv, sha1PartA[8:8+12]...)
aesIv = append(aesIv, sha1PartB[0:8]...)
aesIv = append(aesIv, sha1PartC[16:16+4]...)
aesIv = append(aesIv, sha1PartD[0:8]...)

return aesKey, aesIv
}

// generateAESIGE ЭТО ЕБАНАЯ МАГИЧЕСКАЯ ФУНКЦИЯ ОНА НАХУЙ РАБОТАЕТ ПРОСТО БЛЯТЬ НЕ ТРОГАЙ ШАКАЛ ЕБАНЫЙ
//nolint:godox ты че ебанулся // TODO: порезать себе вены
func generateAESIGE(msg_key, auth_key []byte, decode bool) ([]byte, []byte) {
var x int
if decode {
x = 8
} else {
x = 0
// aes_key = substr (sha256_a, 0, 8) + substr (sha256_b, 8, 16) + substr (sha256_a, 24, 8);
computeAesKey := func(sha256a, sha256b []byte) (v [32]byte) {
n := copy(v[:], sha256a[:8])
n += copy(v[n:], sha256b[8:16+8])
copy(v[n:], sha256a[24:24+8])
return v
}

if len(auth_key) < 96+x+32 {
panic(fmt.Sprintf("wrong len of auth key, got %v want at least %v", len(auth_key), 96+x+32))
// aes_iv = substr (sha256_b, 0, 8) + substr (sha256_a, 8, 16) + substr (sha256_b, 24, 8);
computeAesIV := func(sha256b, sha256a []byte) (v [32]byte) {
n := copy(v[:], sha256a[:8])
n += copy(v[n:], sha256b[8:16+8])
copy(v[n:], sha256a[24:24+8])
return v
}

aes_key := make([]byte, 0, 32)
aes_iv := make([]byte, 0, 32)
t_a := make([]byte, 0, 48)
t_b := make([]byte, 0, 48)
t_c := make([]byte, 0, 48)
t_d := make([]byte, 0, 48)

t_a = append(t_a, msg_key...)
t_a = append(t_a, auth_key[x:x+32]...)

t_b = append(t_b, auth_key[32+x:32+x+16]...)
t_b = append(t_b, msg_key...)
t_b = append(t_b, auth_key[48+x:48+x+16]...)
var sha256a, sha256b [256]byte
// sha256_a = SHA256 (msg_key + substr (auth_key, x, 36));
{
h := sha256.New()

t_c = append(t_c, auth_key[64+x:64+x+32]...)
t_c = append(t_c, msg_key...)
_, _ = h.Write(msgKey)
_, _ = h.Write(authKey[x : x+36])

t_d = append(t_d, msg_key...)
t_d = append(t_d, auth_key[96+x:96+x+32]...)

sha1_a := utils.Sha1Byte(t_a)
sha1_b := utils.Sha1Byte(t_b)
sha1_c := utils.Sha1Byte(t_c)
sha1_d := utils.Sha1Byte(t_d)
h.Sum(sha256a[:0])
}
// sha256_b = SHA256 (substr (auth_key, 40+x, 36) + msg_key);
{
h := sha256.New()

aes_key = append(aes_key, sha1_a[0:8]...)
aes_key = append(aes_key, sha1_b[8:8+12]...)
aes_key = append(aes_key, sha1_c[4:4+12]...)
substr := authKey[40+x:]
_, _ = h.Write(substr[:36])
_, _ = h.Write(msgKey)

aes_iv = append(aes_iv, sha1_a[8:8+12]...)
aes_iv = append(aes_iv, sha1_b[0:8]...)
aes_iv = append(aes_iv, sha1_c[16:16+4]...)
aes_iv = append(aes_iv, sha1_d[0:8]...)
h.Sum(sha256b[:0])
}

return aes_key, aes_iv
return computeAesKey(sha256a[:], sha256b[:]), computeAesIV(sha256a[:], sha256b[:])
}
10 changes: 0 additions & 10 deletions internal/aes_ige/utils.go

This file was deleted.

8 changes: 2 additions & 6 deletions internal/encoding/tl/errors.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
// Copyright£ (c) 2020-2021 KHS Films
//
// This file is a part of mtproto package.
// See https://github.com/amarnathcjd/gogram/blob/master/LICENSE for details

// Copyright (c) 2022,RoseLoverX
package tl

import "fmt"
Expand All @@ -16,7 +12,7 @@ func (e *ErrRegisteredObjectNotFound) Error() string {
return fmt.Sprintf("object with provided crc not registered: 0x%08x", e.Crc)
}

type ErrMustParseSlicesExplicitly null
type ErrMustParseSlicesExplicitly struct{}

func (e *ErrMustParseSlicesExplicitly) Error() string {
return "got vector CRC code when parsing unknown object: vectors can't be parsed as predicted objects"
Expand Down
6 changes: 0 additions & 6 deletions internal/encoding/tl/extra.go

This file was deleted.

Loading

0 comments on commit a9f35a2

Please sign in to comment.