Procházet zdrojové kódy

Add middleproxycipher

tags/0.9
9seconds před 7 roky
rodič
revize
5ea0c4f7bf
1 změnil soubory, kde provedl 97 přidání a 0 odebrání
  1. 97
    0
      mtproto/crypt/crypt.go

+ 97
- 0
mtproto/crypt/crypt.go Zobrazit soubor

@@ -0,0 +1,97 @@
1
+package crypt
2
+
3
+import (
4
+	"bytes"
5
+	"crypto/aes"
6
+	"crypto/cipher"
7
+	"crypto/md5"
8
+	"crypto/sha1"
9
+	"encoding/binary"
10
+	"io"
11
+	"net"
12
+
13
+	"github.com/9seconds/mtg/mtproto/rpc"
14
+	"github.com/9seconds/mtg/wrappers"
15
+)
16
+
17
+type CipherPurpose uint8
18
+
19
+const (
20
+	CipherPurposeClient CipherPurpose = iota
21
+	CipherPurposeServer
22
+)
23
+
24
+var emptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
25
+
26
+func NewMiddleProxyCipherRWC(conn io.ReadWriteCloser, req *rpc.RPCNonceRequest, resp *rpc.RPCNonceResponse, client *net.TCPAddr, remote *net.TCPAddr, secret []byte) io.ReadWriteCloser {
27
+	encryptor := newCBCCipher(CipherPurposeClient, req, resp, client, remote, secret)
28
+	decryptor := newCBCCipher(CipherPurposeServer, req, resp, client, remote, secret)
29
+
30
+	return wrappers.NewBlockCipherRWC(conn, encryptor, decryptor)
31
+}
32
+
33
+func newCBCCipher(purpose CipherPurpose, req *rpc.RPCNonceRequest, resp *rpc.RPCNonceResponse, client *net.TCPAddr, remote *net.TCPAddr, secret []byte) cipher.BlockMode {
34
+	message := bytes.Buffer{}
35
+	message.Write(resp.Nonce[:])
36
+	message.Write(req.Nonce[:])
37
+	message.Write(req.CryptoTS[:])
38
+
39
+	clientIPv4 := emptyIP[:]
40
+	serverIPv4 := emptyIP[:]
41
+	if client.IP.To4() != nil {
42
+		clientIPv4 = reverseBytes(client.IP.To4())
43
+		serverIPv4 = reverseBytes(remote.IP.To4())
44
+	}
45
+	message.Write(serverIPv4)
46
+
47
+	var port [2]byte
48
+	binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
49
+	message.Write(port[:])
50
+
51
+	switch purpose {
52
+	case CipherPurposeClient:
53
+		message.WriteString("CLIENT")
54
+	case CipherPurposeServer:
55
+		message.WriteString("SERVER")
56
+	default:
57
+		panic("Unexpected cipher purpose")
58
+	}
59
+
60
+	message.Write(clientIPv4)
61
+	binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
62
+	message.Write(port[:])
63
+	message.Write(secret)
64
+	message.Write(resp.Nonce[:])
65
+
66
+	if client.IP.To4() == nil {
67
+		message.Write(client.IP.To16())
68
+		message.Write(remote.IP.To16())
69
+	}
70
+	message.Write(req.Nonce[:])
71
+
72
+	return makeCipher(message.Bytes())
73
+}
74
+
75
+func makeCipher(message []byte) cipher.BlockMode {
76
+	md5sum := md5.Sum(message[1:])
77
+	sha1sum := sha1.Sum(message)
78
+
79
+	key := append(md5sum[12:], sha1sum[:]...)
80
+	iv := md5.Sum(message[2:])
81
+
82
+	block, err := aes.NewCipher(key)
83
+	if err != nil {
84
+		panic("Cannot create cipher from the given key")
85
+	}
86
+
87
+	return cipher.NewCBCEncrypter(block, iv[:])
88
+}
89
+
90
+func reverseBytes(data []byte) []byte {
91
+	rv := make([]byte, len(data))
92
+	for k, v := range data {
93
+		rv[len(data)-1-k] = v
94
+	}
95
+
96
+	return rv
97
+}

Načítá se…
Zrušit
Uložit