Ansyen beki sou yon vye beki

Mwen pral kòmanse san yon sekous, yon fwa mwen te gen yon revelasyon (byen, pa trè pwisan, yo dwe onèt) ak lide a leve enprime yon pwogram ki transfere yon imaj soti nan yon kliyan nan yon sèvè. Senp ase dwa? Oke, pou yon pwogramè ki gen eksperyans, li pral konsa. Kondisyon yo senp - pa sèvi ak bibliyotèk twazyèm pati. Nan prensip, li se yon ti kras pi konplike, men yo bay ke ou dwe kalkile li epi gade pou egzanp, byen, tankou yon okipasyon. Mwen deside ke travay sa a se sou mwen. Anplis de sa, li dezirab ke gen ase kòd pou li ka afiche sou fowòm nan si ou bezwen èd. Premye a tout, je m 'te tonbe sou FTP, nan chemen an, eksplwatasyon an nan ki Windows ap devlope. Avantaj nan FTP se ke ou ka transfere pa sèlman yon imaj, men nenpòt ki dosye atravè li. Apre telechaje Filezilla Server, pataje yon sèl anyè pou lekti / ekri ak kreye yon itilizatè ak yon modpas, mwen te eseye konekte Filezilla Kliyan, tout bagay te travay. Mwen te kreye yon egzanp kòd senp nan C/C++:

#include <iostream>
void main()
{
	FILE* fs;
	fopen_s(&fs, "1.txt", "w");
	if (fs)
	{
    fwrite("userrnpasswordrnsend D:\share.txtrnbye", 1, sizeof("userrnpasswordrnsend D:\share.txtrnbye"), fs);
    fwrite("00", 1, sizeof("00"), fs);
    fclose(fs);
	}
	system("ftp -s:1.txt 127.0.0.1");
}

Si memwa mwen sèvi m ', Lè sa a, tout bagay te travay sou localhost la, ak lè transmèt sou rezo a, yon erè ki te fèt nan liy lan ak voye. Ki sa ki pratik isit la a) yon ti tan b) ou pa bezwen enstale yon kliyan, men sèvi ak zouti ki deja entegre pou ftp soti nan Microsoft. Malgre ke nan opinyon mwen li dwe aktive atravè pwogram ak eleman. Si ou kalkile ki pwoblèm metòd sa a se epi ekri nan kòmantè yo, li pral gwo.

Mwen pa jwenn yon repons sou yon pakèt fowòm, mwen kite kòd sa a epi mwen deside sèvi ak koòdone a pou rezo socket. Mwen deja gen eksperyans nan pase yon etalaj de karaktè nan yon lòt pwogram. By wout la, ou ka li nan Tanenbaum, Rezo òdinatè, nan chapit la sou kouch transpò a. Gen yon egzanp yon kliyan ak yon sèvè, men se pa pou koneksyon "anpil kliyan - yon sèl sèvè", men se sèlman "yon kliyan - yon sèl sèvè". Depi transmisyon an se sou entènèt la, ou bezwen ankripte done yo yon jan kanmenm. Pou sa, yo itilize yon chifreman blòk - rezo Feistel. Plus sou sèvè a li nesesè pou fè plizyè (plis pase yon kliyan) kliyan. Pou fè sa, nou pral sèvi ak Threads, imaj la pou transmisyon pral pran yon Ekran nan ekran an nan men kliyan an, dwe chiffres ak transmèt nan sèvè a, kote li pral dechifre epi imedyatman parèt sou ekran an atravè pwogram nan default pou ouvèti * .tga imaj.

Kòd sèvè:

#include <iostream>
#include <WinSock.h>
#pragma comment (lib,"WS2_32.lib")

#include <fstream>
#include <algorithm>
#include <string>
#include <iterator>
#include <vector>
void error(const char* msg)
{
    //perror(msg);
    std::cout<<'n'<<WSAGetLastError();
    WSACleanup();
    std::cin.ignore();
    exit(1);
}
void bzero(char*buf, int l)
{
    for (int i = 0; i < l; i++)
        buf[i] = '';
}
struct arg_s
{
    unsigned char* buffer2;
    bool exit;
};
char** buffer;
struct arg_sa
{
    struct arg_s* lalk;
    int current;
};
#define type struct arg_sa
int sockfd, * newsockfd;//слушающий и массив клиентских сокетов
int buflen2 = 10292000;//максимальный размер изображения в байтах для RGBA*Width*Height
struct sockaddr_in *cli_addr;
int* clilen;
int currentclient,cc;//сс-клиент по счету(для записи инкремента имени файла клиента изображения)

typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
#define N 8//размер блока
#define F32 0xFFFFFFFF
uint32_t RK[N];//раундовые ключи
#define size64 sizeof(uint64_t)
#define ROR(x,n,xsize)((x>>n)|(x<<(xsize-n)))
#define ROL(x,n,xsize)((x<<n)|(x>>(xsize-n)))
#define RKEY(r)((ROR(K,r*3,size64*8))&F32)
const uint64_t K = 0x96EA704CFB1CF671;//ключ шифрования
struct hostent* server;
uint32_t F(uint32_t subblk, uint32_t key)
{
    return subblk + key;//функция шифрования
}
void createRoundKeys()
{
    for (int i = 0; i < N; i++)
        RK[i] = (ROR(K, i * 8, size64 * 8)) & F32;
}
uint64_t decrypt(uint64_t c_block)//расшифровка блоков сетью фейстеля
{
    //select subblocks
    uint32_t left = (c_block >> 32) & F32;
    uint32_t right = c_block & F32;
    uint32_t left_, right_;//subblock in the end of round
    for (int r = N - 1; r >= 0; r--)
    {
        uint32_t fk = F(left, RK[r]);
        left_ = left;
        right_ = right ^ fk;
        if (r > 0)//swap places to next round
        {
            left = right_;
            right = left_;
        }
        else //last round not swap
        {
            left = left_;
            right = right_;
        }
    }
    //collect subblock in block
    uint64_t block = left;
    block = (block << 32) | (right & F32);
    return block;
}
void session_(LPVOID args)//функция потока ля каждого клиента
{
    int current = currentclient++;
    bzero((char*)&(cli_addr[current]), sizeof(&(cli_addr[current])));
    newsockfd[current] = accept(sockfd, (struct sockaddr*)&(cli_addr[current]), &(clilen[current]));
    if (newsockfd[current] < 0)
    {
        error("Error on acceptn");
    }
    char* s = new char[100];
    int n = recv(newsockfd[current], s, 100, 0);
    int buflen2 = atoi(s);//получаем число байтов изображения
    FILE* f;
    std::string name = "Screen";
    cc++;
    _itoa_s(cc, s, 100, 10);
    name += s;
    name += ".tga";
    fopen_s(&f,name.c_str(), "wb");//создаем файл изображения с увеличиваещимся на 1 именем, чтобы не перезаписать
    if (f != NULL)
    {
        unsigned char tgaHeader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        unsigned char header[6];
        n = recv(newsockfd[current], buffer[current], sizeof(tgaHeader), 0);
        fwrite((unsigned char*)buffer[current], 1, sizeof(tgaHeader), f);
        bzero(buffer[current], buflen2);
        n = recv(newsockfd[current], buffer[current],sizeof(header), 0);
        fwrite((unsigned char*)buffer[current], 1, sizeof(header), f);//записали хидеры
        bzero(buffer[current], buflen2);
        n = recv(newsockfd[current], buffer[current], buflen2, 0);//получили байты самого изображения
        //
        //расшифровка байтов
        createRoundKeys();
        unsigned long long id;
        std::vector<uint64_t>* plaintext = new std::vector<uint64_t>();
        int i = 0;
        while (i<buflen2)
        {
            memcpy(&id, (buffer[current]) + i, N);
            plaintext->push_back(decrypt(id));
            i += 8;
        }
        std::cout << "i=" << i << std::endl;
        i = 0;
        char str_[N + 1];
        memset(str_, 0, N);
        str_[N] = '';
        for (std::vector<uint64_t>::iterator it = plaintext->begin(); it != plaintext->end(); ++it)
        {
            memcpy(str_, &*it, N);
            fwrite((unsigned char*)str_, sizeof(unsigned char), N/*strlen(str_)*/, f);
            i += 8;
        }
        std::cout << "i=" << i << std::endl;
        //конец рашифровки байтов
        //fwrite((unsigned char*)buffer[current], sizeof(char), buflen2, f);
        fclose(f);
    }
    system(name.c_str());//открываем изображение *.tga встроенным редактором
}
int main()
{
    cc = 0;
    WSADATA ws = { 0 };
    if (WSAStartup(MAKEWORD(2, 2), &ws) == 0)
    {
        currentclient = 0;
        int maxclients = 2;//максимальное число клиентов
        cli_addr = new struct sockaddr_in[maxclients];
        clilen = new int[maxclients];
        buffer = new char* [maxclients];
        for (int i = 0; i < maxclients; i++)
        {
            clilen[i] = sizeof(cli_addr[i]);
        }
        sockfd = socket(AF_INET, SOCK_STREAM, 0);//tcp сокет
        if (sockfd < 0)
            error("ERROR opening socket");
        struct sockaddr_in serv_addr;
        bzero((char*)&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        int port = 30000;//порт
        serv_addr.sin_port = htons(port);
        if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
            error("ERROR on binding");
        if (listen(sockfd, 10) < 0)
            error("ERROR listen");
        HANDLE* thread;//массив потоков для каждого клиента отдельный
        struct arg_sa* args;
        while (true)
        {
            newsockfd = new int[maxclients];
            thread = (HANDLE*)malloc(sizeof(HANDLE) * maxclients);
            args = new struct arg_sa[maxclients];
            for (int i = 0; i < maxclients; i++)
            {
                args[i].lalk = new struct arg_s();
                buffer[i] = new char[buflen2];
            }
            int i = -1;
            while (++i < maxclients)
            {
                Sleep(1);
                args[i].current = i;
                args[i].lalk->exit = false;
                thread[i] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)(session_), args, 0, 0);
            }
                for (int i = 0; i < maxclients; i++)
                    WaitForSingleObject(thread[i], INFINITE);//ждем завершения всех потоков
            i = -1;
            while (++i < maxclients)
            {
                shutdown(newsockfd[i], 0);
                TerminateThread(thread[i], 0);
            }
            //delete[] newsockfd;
            //free(thread);
            currentclient = 0;
            for (int i = 0; i < maxclients; i++)
            {
                //delete args[i].lalk;
                //delete[] args[i].lalk->buffer;
            }
            //delete[] args;
        }
        shutdown(sockfd, 0);
        WSACleanup();
        return 0;
    }
    std::cin.ignore();
}

Nan ti bout tan, nan yon bouk p'ap janm fini an, fil yo kreye pou chak kliyan epi tann pou aksepte jiskaske kliyan konekte. Apre sa, WaitForSingleObject tann jiskaske yo tout pase. Chak kliyan gen priz pwòp li yo ak pwòp tanpon voye li yo. Sa vle di, gen M+1 priz sou sèvè a, kote M se kantite kliyan. Apre tout transfè yo fini, tout bagay repete.

Koulye a, konsidere kliyan an:

#include <iostream>
#include <WinSock.h>
#include <vector>
#pragma comment (lib,"WS2_32.lib")
void error(const char* msg)
{
    //perror(msg);
    std::cout << 'n' << WSAGetLastError();
    WSACleanup();
    std::cin.ignore();
    exit(1);
}
void bzero(char* buf, int l)
{
    for (int i = 0; i < l; i++)
        buf[i] = '';
}
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
#define N 8
#define F32 0xFFFFFFFF
uint32_t RK[N];//раундовые ключи
#define size64 sizeof(uint64_t)
#define ROR(x,n,xsize)((x>>n)|(x<<(xsize-n)))
#define ROL(x,n,xsize)((x<<n)|(x>>(xsize-n)))
#define RKEY(r)((ROR(K,r*3,size64*8))&F32)
const uint64_t K = 0x96EA704CFB1CF671;//ключ шифрования
void createRoundKeys()
{
    for (int i = 0; i < N; i++)
        RK[i] = (ROR(K, i * 8, size64 * 8)) & F32;
}
uint32_t F(uint32_t subblk, uint32_t key)
{
    return subblk + key;//функция шифрования
}
uint64_t encrypt(uint64_t block)//зашифровка блоков сетью Фейстеля
{
    //select subblocks
    uint32_t left = (block >> 32) & F32;
    uint32_t right = block & F32;
    uint32_t left_, right_;//subblock in the end of round
    for (int r = 0; r < N; r++)
    {
        uint32_t fk = F(left, RK[r]);
        left_ = left;
        right_ = right ^ fk;
        if (r < N - 1)//swap places to next round
        {
            left = right_;
            right = left_;
        }
        else//last round not swap
        {
            left = left_;
            right = right_;
        }
    }
    //collect subblock in block
    uint64_t c_block = left;
    c_block = (c_block << 32) | (right & F32);
    return c_block;
}
int main()
{
    keybd_event(VK_LWIN, 0, 0, 0);
    keybd_event('M', 0, 0, 0);
    keybd_event('M', 0, KEYEVENTF_KEYUP, 0);
    keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0);//эти строки сворачивают все приложения
    Sleep(1000);//чтобы сделать скриншот рабочего стола
    WSADATA ws = { 0 };
    if (WSAStartup(MAKEWORD(2, 2), &ws) == 0)
    {
        int sockfd;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in serv_addr, cli_addr;
        bzero((char*)&serv_addr, sizeof(serv_addr));
        bzero((char*)&cli_addr, sizeof(cli_addr));
        serv_addr.sin_family = AF_INET;

        const char* add = "127.0.0.1";//адрес сервера
        serv_addr.sin_addr.s_addr = inet_addr(add);
        int port = 30000;//порт
        serv_addr.sin_port = htons(port);
        int servlen = sizeof(serv_addr);
        int n = connect(sockfd, (struct sockaddr*)&serv_addr, servlen);
        
        //ниже код делает скриншот
        HDC ScreenDC = GetDC(0);
        HDC MemoryDC = CreateCompatibleDC(ScreenDC);
        int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
        int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
        ScreenWidth = ((ScreenWidth - 1) / 4 + 1) * 4;
        BITMAPINFO BMI;
        BMI.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        BMI.bmiHeader.biWidth = ScreenWidth;
        BMI.bmiHeader.biHeight = ScreenHeight;
        BMI.bmiHeader.biSizeImage = ScreenWidth * ScreenHeight * 3;
        BMI.bmiHeader.biCompression = BI_RGB;
        BMI.bmiHeader.biBitCount = 24;
        BMI.bmiHeader.biPlanes = 1;
        DWORD ScreenshotSize;
        ScreenshotSize = BMI.bmiHeader.biSizeImage;
        unsigned char* ImageBuffer;
        HBITMAP hBitmap = CreateDIBSection(ScreenDC, &BMI, DIB_RGB_COLORS, (void**)&ImageBuffer, 0, 0);
        SelectObject(MemoryDC, hBitmap);
        BitBlt(MemoryDC, 0, 0, ScreenWidth, ScreenHeight, ScreenDC, 0, 0, SRCCOPY);
        DeleteDC(MemoryDC);
        ReleaseDC(NULL, ScreenDC);
        FILE* sFile = 0;
        unsigned char tgaHeader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        unsigned char header[6];
        unsigned char tempColors = 0;
        fopen_s(&sFile, "S.tga", "wb");
        if (!sFile) {
            exit(1);
        }
        header[0] = ScreenWidth % 256;
        header[1] = ScreenWidth / 256;
        header[2] = ScreenHeight % 256;
        header[3] = ScreenHeight / 256;
        header[4] = BMI.bmiHeader.biBitCount;
        header[5] = 0;
        fwrite(tgaHeader, 1, sizeof(tgaHeader), sFile);
        fwrite(header, sizeof(header), 1, sFile);
        //конец записали изображение в файл
        
        //шифруем блоками полезную нагрузку изображения кроме хидеров
        createRoundKeys();
        std::vector<uint64_t>* msg = new std::vector<uint64_t>(),*crpt = new std::vector<uint64_t>();
        unsigned long long id;
        int i = 0;
        while (i < BMI.bmiHeader.biSizeImage)
        {
            memcpy(&id, (ImageBuffer + i), N);
            msg->push_back(id);
            i += 8;
        }
        std::cout << "i=" << i << std::endl; 
        uint64_t cipher;
        i = 0;
        char str_[N + 1];
        memset(str_, 0, N);
        str_[N] = '';
        for (std::vector<uint64_t>::iterator it = msg->begin(); it != msg->end(); ++it)
        {
            cipher = encrypt(*it);
            memcpy(str_, &cipher, N);
            fwrite((unsigned char*)str_, sizeof(unsigned char), N, sFile);
            i += 8;
        }
        std::cout << "i=" << i << std::endl;
        //
        //fwrite(ImageBuffer, BMI.bmiHeader.biSizeImage, 1, sFile);
        std::cout << BMI.bmiHeader.biSizeImage << std::endl;
        fclose(sFile);
        DeleteObject(hBitmap);
        FILE* f;
        fopen_s(&f, "S.tga", "rb");
        int count = 0;
        if (f != NULL)
        {
            while (getc(f) != EOF)
                count++;//считаем байты изображения в счетчик чтобы потом передать
            fclose(f);
        }
        count -= 18;
        std::cout << count<< std::endl;
        char* s = new char[100];
        _itoa_s(count, s, 100, 10);
        n = send(sockfd, s, 100, 0);//передаем счетчик
        char* buffer = new char[count];
        fopen_s(&f, "S.tga", "rb");
        size_t bytes;
        if (f != NULL)
        {
            memcpy(buffer, tgaHeader, sizeof(tgaHeader));
            n = send(sockfd, buffer, sizeof(tgaHeader), 0);
            bzero(buffer, count);
            memcpy(buffer, header, sizeof(header));
            n = send(sockfd, buffer, sizeof(header), 0);
            bzero(buffer, count);//передаем хидеры
            for(int i=0;i<18;i++)
                fgetc(f);
            bzero(buffer, count);
            bytes = fread(buffer, sizeof(unsigned char), count, f);
            n = send(sockfd,buffer, count, 0);//передаем шифрованные байты изображения
            fclose(f);
        }
        Sleep(1000);
        shutdown(sockfd, 0);
        WSACleanup();
        //system("del S.tga");
        delete[] buffer,s;
        return 0;
    }
    //std::cin.ignore();
}

Men rezilta travay kliyan an, dosye S.tga ekran an, kode

Ansyen beki sou yon vye beki

Li sanble ke li se yon Desktop.

Ak isit la se rezilta a ki te transfere nan sèvè a ak dekode pa Screen.tga

Ansyen beki sou yon vye beki

Kòm ou ka wè, rezo Feistel abityèl la pa apwopriye pou chifreman, men ou ka itilize metòd CBC ak CFB, li pral pwobableman pi bon chiffres, yo dwe onèt, mwen pa t 'tcheke li.

Mèsi pou atansyon ou!

Sous: www.habr.com

Add nouvo kòmantè