Я пытаюсь отправить BIGNUM (из openssl / bn.h) через сокет, но его поведение странное.
я использую BN_bn2bin()
конвертировать BIGNUM в массив unsigned char
и отправить его через сокет, используя send()
, Но то, что получает клиент, повреждено. Зачем?
Вот минимальный рабочий образец:
server.cpp
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <cstdlib>
#include <openssl/bn.h>
using namespace std;
int main() {
// Set up
int result;
int opt_val = 1;
int port = 12345;
int listen_sock;
int peer_sock;
struct sockaddr_in address;
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = INADDR_ANY;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val));
result = bind(listen_sock, (struct sockaddr*)&address, sizeof(address));
if (result != 0) {
cerr << "bind() failed." << endl;
exit(result);
}
result = listen(listen_sock, 5);
if (result != 0) {
cerr << "listen() failed." << endl;
exit(result);
}
size_t size = sizeof(address);
peer_sock = accept(listen_sock, (struct sockaddr*)&address, (socklen_t *)&size);
if (peer_sock < 0) {
cerr << "accept() failed." << endl;
exit(result);
}
////////////////////////////////
// Prepare BIGNUM
BIGNUM* bn = BN_new();
BN_rand(bn, 1024, 0, 0);
size = BN_num_bytes((const BIGNUM*)bn);
// Send using fixed array
unsigned char fixed[size];
BN_bn2bin((const BIGNUM*)bn, fixed);
// Send using dynamic array
unsigned char *dynamic;
dynamic = new unsigned char[size];
BN_bn2bin((const BIGNUM*)bn, dynamic);
// First let's compare
if ( memcmp(fixed, dynamic, size) != 0) {
cout << "Fixed and dynamic do not equal" << endl;
exit(-1);
}
// Then let's send two arrays
send(peer_sock, &size, sizeof(size), MSG_MORE);
send(peer_sock, fixed, size, MSG_MORE);
send(peer_sock, dynamic, size, MSG_MORE);
}
client.cpp
#include <netinet/in.h>
#include <iostream>
#include <netdb.h>
#include <cstdlib>
#include <arpa/inet.h>
#include <openssl/bn.h>
#include <cstring>
using namespace std;
int main() {
struct addrinfo* res;
struct sockaddr_in address;
int peer_port = 12345;
int self_sock;
string peer_ip = "127.0.0.1";
address.sin_family = AF_INET;
address.sin_port = htons(peer_port);
int result = getaddrinfo((const char*)peer_ip.c_str(), NULL, NULL, &res);
if (result != 0) {
std::cerr << "Peer hostname invalid." << std::endl;
exit(-1);
}
freeaddrinfo(res);
inet_pton(AF_INET, (const char*)peer_ip.c_str(), &(address.sin_addr));
self_sock = socket(AF_INET, SOCK_STREAM, 0);
if (::connect(self_sock, (struct sockaddr*)&address, sizeof(address)) != 0) {
std::cerr << "connect() failed." << std::endl;
exit(-1);
}int size;
recv(self_sock, &size, sizeof(size), 0);
// Receive fixed array
unsigned char fixed[size];
unsigned char* dynamic = new unsigned char[size];
recv(self_sock, fixed, size, 0);
recv(self_sock, dynamic, size, 0);
if (memcmp(fixed, dynamic, size) != 0) {
cerr << "client: fixed and dynamic are different!" << endl;
exit(-1);
}
BIGNUM* bn_fixed = BN_new();
BIGNUM* bn_dynamic = BN_new();
BN_bin2bn((const unsigned char*)fixed, size, bn_fixed);
BN_bin2bn((const unsigned char*)dynamic, size, bn_dynamic);
if (BN_cmp((const BIGNUM*)bn_fixed, (const BIGNUM*)bn_dynamic) != 0) {
cerr << "bn_fixed and bn_dynamic are different!" << endl;
exit(-1);
}
return 0;
}
Сборка как с g++ -o <server/client> <server.cpp/client.cpp> -lssl -lcrypto
я использовал memcmp
и проверил, что память fixed
а также dynamic
точки равны друг другу, но fixed
а также dynamic
Получаемые клиентом абсолютно разные друг от друга и исходные сообщения. Я сомневаюсь, что это может быть потому, что я использую localhost, но когда я попытался использовать две независимые машины, это все еще происходит.
Задача ещё не решена.
Других решений пока нет …