[Криптография, Сетевые технологии, C++, Разработка под Windows, Обработка изображений] Древний костыль на старом костыле
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Начну без обиняков, как-то раз меня постигло откровение(ну не сильно мощное скажу по-честному) и возникла идея напечатать программу которая передает изображение с клиента на сервер. Достаточно просто да? Ну для программиста со стажем так и будет. Условия просты - не использовать сторонние библиотеки. В принципе немного сложнее, но если учесть что придется разбираться и искать примеры, ну такое себе занятие. Я решил, что эта задача мне по плечу. Плюс желательно чтобы было кода столько, чтобы его можно было запостить на форуме, в случае если понадобится помощь. В первую очередь мой взгляд пал на FTP, к слову ОС в которой разрабатывается Windows. Плюс FTP в том, что можно через него передать не только изображение, а любой файл. Скачав Filezilla Server, расшарив одну директорию на чтение/запись и создав юзера с паролем, попробовал подключится Filezilla Client все работало. Создал простенький пример кода на С/С++:
#include <iostream>
void main()
{
FILE* fs;
fopen_s(&fs, "1.txt", "w");
if (fs)
{
fwrite("user\r\npassword\r\nsend D:\\share\\1.txt\r\nbye", 1, sizeof("user\r\npassword\r\nsend D:\\share\\1.txt\r\nbye"), fs);
fwrite("\000", 1, sizeof("\000"), fs);
fclose(fs);
}
system("ftp -s:1.txt 127.0.0.1");
}
Если мне не изменяет память, то на локалхосте все работало, а при передаче по сети возникала ошибка в строчке с send. Что здесь удобно а)коротко б)не нужно устанавливать клиент, а использовать уже встроенную тулзу для ftp от майкрософта. Хотя по-мойму ее надо активировать через программы и компоненты. Если вы разберетесь в чем проблема данного метода и напишите в комментарии, будет отлично.Не найдя ответа на куче форумов, я оставил данный код и решил использовать интерфейс для сетей сокеты. У меня уже был опыт передачи массива char'ов для другой программы. Кстати можете почитать у Таненбаума, Компьютерные сети, в главе про транспортный уровень. Там есть пример клиента и сервера, правда не для соединения "много клиентов - один сервер", а только "один клиент - один сервер". Поскольку передача идет через Интернет, то нужно зашифровать хоть как-то данные. Для этого используется блочный шифр - сеть Фейстеля. Плюсом на сервере надо сделать несколько(больше одного клиента) клиентов. Для этого воспользуемся Thread'ами, изображение для передачи будет брать скриншот экрана с клиента шифроваться и передаваться на сервер, на котором будет расшифровано и сразу же выведено на экран через дефолтную программу для открытия *.tga изображения.Код сервера:
#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] = '\0';
}
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 accept\n");
}
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] = '\0';
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();
}
Вкратце в вечном цикле создаются потоки для каждого клиента и ждут accept пока клиенты подключится. После чего WaitForSingleObject ждет пока они все передадут. У каждого клиента свой сокет и свой буфер передачи. То есть на сервере M+1 сокет, где M количество клиентов. После завершения всех передач, всё повторяется. Теперь рассмотрим клиент:
#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] = '\0';
}
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] = '\0';
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();
}
Вот результат работы клиента файл скриншота S.tga, зашифрованный
Видно, что это рабочий столА вот результат который был передан на сервер и расшифрован Screen.tga
Как видите обычная сеть Фейстеля не подходит для шифрования, но можно воспользоваться CBC и CFB методами, возможно будет лучше зашифровано, если честно не проверял. Спасибо за внимание!
===========
Источник:
habr.com
===========
Похожие новости:
- [Криптография, Платежные системы, Программирование] Блокчейн-платформа R-chain: общая архитектура и эволюция
- [Сетевые технологии, Старое железо, Сетевое оборудование] Старый ламповый телевизор ежедневно приводил к падению ADSL-соединения в целой деревне
- [Законодательство в IT, Обработка изображений, Социальные сети и сообщества] Facebook запустила раздел контроля контента для владельцев авторских прав
- [Информационная безопасность, Open source, Обработка изображений, Киберпанк, TensorFlow] Защита фото от систем распознавания лиц работает?
- [Алгоритмы, Искусственный интеллект, Обработка изображений] В Photoshop появится функция на ИИ для замены неба
- [Информационная безопасность, Разработка под Windows, Софт] В США потребовали от организаций установить последние патчи безопасности для Windows Server из-за серьёзных уязвимостей
- [C++, Компьютерное железо, Разработка под Windows, Системное программирование] О работе ПК ч.3: От включения до полной загрузки Windows 10
- [C, C++, Rust] Предпочитайте Rust вместо C/C++ для нового кода (перевод)
- [Конференции] Ламповые стримы этой недели от JUG Ru Group: дискуссия с «Королем разработки» и не только
- [Информационная безопасность, Разработка под Android, Разработка под Windows, Системы обмена сообщениями] Хакеры из Ирана годами воровали личные данные и прослушивали пользователей Telegram
Теги для поиска: #_kriptografija (Криптография), #_setevye_tehnologii (Сетевые технологии), #_c++, #_razrabotka_pod_windows (Разработка под Windows), #_obrabotka_izobrazhenij (Обработка изображений), #_set_fejstelja (сеть фейстеля), #_sokety (сокеты), #_izobrazhenija (изображения), #_shifrovanie (шифрование), #_set (сеть), #_kriptografija (
Криптография
), #_setevye_tehnologii (
Сетевые технологии
), #_c++, #_razrabotka_pod_windows (
Разработка под Windows
), #_obrabotka_izobrazhenij (
Обработка изображений
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:52
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Начну без обиняков, как-то раз меня постигло откровение(ну не сильно мощное скажу по-честному) и возникла идея напечатать программу которая передает изображение с клиента на сервер. Достаточно просто да? Ну для программиста со стажем так и будет. Условия просты - не использовать сторонние библиотеки. В принципе немного сложнее, но если учесть что придется разбираться и искать примеры, ну такое себе занятие. Я решил, что эта задача мне по плечу. Плюс желательно чтобы было кода столько, чтобы его можно было запостить на форуме, в случае если понадобится помощь. В первую очередь мой взгляд пал на FTP, к слову ОС в которой разрабатывается Windows. Плюс FTP в том, что можно через него передать не только изображение, а любой файл. Скачав Filezilla Server, расшарив одну директорию на чтение/запись и создав юзера с паролем, попробовал подключится Filezilla Client все работало. Создал простенький пример кода на С/С++: #include <iostream>
void main() { FILE* fs; fopen_s(&fs, "1.txt", "w"); if (fs) { fwrite("user\r\npassword\r\nsend D:\\share\\1.txt\r\nbye", 1, sizeof("user\r\npassword\r\nsend D:\\share\\1.txt\r\nbye"), fs); fwrite("\000", 1, sizeof("\000"), fs); fclose(fs); } system("ftp -s:1.txt 127.0.0.1"); } #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] = '\0'; } 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 accept\n"); } 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] = '\0'; 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(); } #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] = '\0'; } 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] = '\0'; 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(); } Видно, что это рабочий столА вот результат который был передан на сервер и расшифрован Screen.tga Как видите обычная сеть Фейстеля не подходит для шифрования, но можно воспользоваться CBC и CFB методами, возможно будет лучше зашифровано, если честно не проверял. Спасибо за внимание! =========== Источник: habr.com =========== Похожие новости:
Криптография ), #_setevye_tehnologii ( Сетевые технологии ), #_c++, #_razrabotka_pod_windows ( Разработка под Windows ), #_obrabotka_izobrazhenij ( Обработка изображений ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:52
Часовой пояс: UTC + 5