Add middleproxycipher

This commit is contained in:
9seconds
2018-07-02 13:56:19 +03:00
parent 420159a7d3
commit 5ea0c4f7bf
+97
View File
@@ -0,0 +1,97 @@
package crypt
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/sha1"
"encoding/binary"
"io"
"net"
"github.com/9seconds/mtg/mtproto/rpc"
"github.com/9seconds/mtg/wrappers"
)
type CipherPurpose uint8
const (
CipherPurposeClient CipherPurpose = iota
CipherPurposeServer
)
var emptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
func NewMiddleProxyCipherRWC(conn io.ReadWriteCloser, req *rpc.RPCNonceRequest, resp *rpc.RPCNonceResponse, client *net.TCPAddr, remote *net.TCPAddr, secret []byte) io.ReadWriteCloser {
encryptor := newCBCCipher(CipherPurposeClient, req, resp, client, remote, secret)
decryptor := newCBCCipher(CipherPurposeServer, req, resp, client, remote, secret)
return wrappers.NewBlockCipherRWC(conn, encryptor, decryptor)
}
func newCBCCipher(purpose CipherPurpose, req *rpc.RPCNonceRequest, resp *rpc.RPCNonceResponse, client *net.TCPAddr, remote *net.TCPAddr, secret []byte) cipher.BlockMode {
message := bytes.Buffer{}
message.Write(resp.Nonce[:])
message.Write(req.Nonce[:])
message.Write(req.CryptoTS[:])
clientIPv4 := emptyIP[:]
serverIPv4 := emptyIP[:]
if client.IP.To4() != nil {
clientIPv4 = reverseBytes(client.IP.To4())
serverIPv4 = reverseBytes(remote.IP.To4())
}
message.Write(serverIPv4)
var port [2]byte
binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
message.Write(port[:])
switch purpose {
case CipherPurposeClient:
message.WriteString("CLIENT")
case CipherPurposeServer:
message.WriteString("SERVER")
default:
panic("Unexpected cipher purpose")
}
message.Write(clientIPv4)
binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
message.Write(port[:])
message.Write(secret)
message.Write(resp.Nonce[:])
if client.IP.To4() == nil {
message.Write(client.IP.To16())
message.Write(remote.IP.To16())
}
message.Write(req.Nonce[:])
return makeCipher(message.Bytes())
}
func makeCipher(message []byte) cipher.BlockMode {
md5sum := md5.Sum(message[1:])
sha1sum := sha1.Sum(message)
key := append(md5sum[12:], sha1sum[:]...)
iv := md5.Sum(message[2:])
block, err := aes.NewCipher(key)
if err != nil {
panic("Cannot create cipher from the given key")
}
return cipher.NewCBCEncrypter(block, iv[:])
}
func reverseBytes(data []byte) []byte {
rv := make([]byte, len(data))
for k, v := range data {
rv[len(data)-1-k] = v
}
return rv
}