我正在尝试通过套接字发送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,但是当我尝试使用两台独立的机器时,它仍然会发生。