嗨,我是第一次接触openssl,我正在尝试使用openssl实现匿名Diffie Hellman连接。
代码服务器代码看起来像这样:
#include "openssl/err.h"
#include "openssl/ssl.h"
#include "openssl/dh.h"
#include <arpa/inet.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <resolv.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define FAIL -1
// Create the SSL socket and intialize the socket address structure
int OpenListener(int port) {
int sd;
struct sockaddr_in addr;
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("can't bind port");
abort();
}
if (listen(sd, 10) != 0) {
perror("Can't configure listening port");
abort();
}
return sd;
}
int isRoot() {
if (getuid() != 0) {
return 0;
} else {
return 1;
}
}
SSL_CTX *InitServerCTX(void) {
SSL_METHOD *method;
SSL_CTX *ctx;
DH *dh_;
int codes = 0;
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
method = TLSv1_2_server_method(); /* create new server-method instance */
ctx = SSL_CTX_new(method); /* create new context from method */
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
abort();
}
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA256") != 1) {
ERR_print_errors_fp(stderr);
abort();
}
dh_ = DH_new();
if (dh_ == NULL) {
printf ("Alloc for dh failed\n");
ERR_print_errors_fp(stderr);
abort();
}
// Generate Parameters.
if (!DH_generate_parameters_ex (dh_, 1024, DH_GENERATOR_5, NULL)) {
printf ("Generate Parameters failed!!\n");
ERR_print_errors_fp(stderr);
abort();
ERR_print_errors_fp(stderr);
}
// Check if p and g parameters are safe to use.
if (!DH_check (dh_, &codes)) {
printf ("Cannot perform DH check\n");
ERR_print_errors_fp(stderr);
abort();
}
if (codes) {
printf ("DH codes: %x\n", codes);
ERR_print_errors_fp(stderr);
abort();
}
if (!DH_generate_key (dh_)) {
printf ("Failure in DH Generate key\n");
ERR_print_errors_fp(stderr);
abort();
}
SSL_CTX_set_tmp_dh(ctx, dh_);
DH_free(dh_);
return ctx;
}
void Servlet(SSL *ssl) /* Serve the connection -- threadable */
{
char buf[1024] = {0};
int sd, bytes;
const char *ServerResponse = "<\Body>\
<Name>aticleworld.com</Name>\
<year>1.5</year>\
<BlogType>Embedede and c\c++<\BlogType>\
<Author>amlendra<Author>\
<\Body>";
const char *cpValidMessage = "<Body>\
<UserName>aticle<UserName>\
<Password>123<Password>\
<\Body>";
if (SSL_accept(ssl) == FAIL) /* do SSL-protocol accept */
ERR_print_errors_fp(stderr);
else {
//ShowCerts(ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
buf[bytes] = '\0';
printf("Client msg: \"%s\"\n", buf);
if (bytes > 0) {
if (strcmp(cpValidMessage, buf) == 0) {
SSL_write(ssl, ServerResponse, strlen(ServerResponse)); /* send reply */
} else {
SSL_write(ssl, "Invalid Message",
strlen("Invalid Message")); /* send reply */
}
} else {
ERR_print_errors_fp(stderr);
}
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
}
int main(int count, char *Argc[]) {
SSL_CTX *ctx;
int server;
char *portnum;
// Only root user have the permsion to run the server
if (!isRoot()) {
printf("This program must be run as root/sudo user!!");
exit(0);
}
if (count != 2) {
printf("Usage: %s <portnum>\n", Argc[0]);
exit(0);
}
// Initialize the SSL library
SSL_library_init();
portnum = Argc[1];
ctx = InitServerCTX(); /* initialize SSL */
server = OpenListener(atoi(portnum)); /* create server socket */
while (1) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
int client = accept(server, (struct sockaddr *)&addr,
&len); /* accept connection as usual */
printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port));
ssl = SSL_new(ctx); /* get new SSL state with context */
SSL_set_fd(ssl, client); /* set connection socket to SSL state */
Servlet(ssl); /* service connection */
}
close(server); /* close server socket */
SSL_CTX_free(ctx); /* release context */
}
客户端程序如下:
#include <errno.h>
#include <malloc.h>
#include <netdb.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/dh.h>
#include <resolv.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define FAIL -1
int OpenConnection(const char *hostname, int port) {
int sd;
struct hostent *host;
struct sockaddr_in addr;
if ((host = gethostbyname(hostname)) == NULL) {
perror(hostname);
abort();
}
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long *)(host->h_addr);
printf ("Connecting....\n");
if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
close(sd);
perror(hostname);
abort();
} else {
printf ("Connected...\n");
}
return sd;
}
SSL_CTX *InitCTX(void) {
SSL_METHOD *method;
SSL_CTX *ctx;
DH *dh_;
int codes = 0;
OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
SSL_load_error_strings(); /* Bring in and register error messages */
method = TLSv1_2_client_method(); /* Create new client-method instance */
ctx = SSL_CTX_new(method); /* Create new context */
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
abort();
}
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA256") != 1) {
printf("SSL_CTX_set_cipher_list failed\n");
SSL_CTX_free (ctx);
ctx = NULL;
ERR_print_errors_fp(stderr);
abort();
}
dh_ = DH_new();
if (dh_ == NULL) {
printf ("Alloc for dh failed\n");
}
// Generate Parameters.
if (!DH_generate_parameters_ex (dh_, 1024, DH_GENERATOR_5, NULL)) {
printf ("Generate Parameters failed!!\n");
}
// Check if p and g parameters are safe to use.
if (!DH_check (dh_, &codes)) {
printf ("Cannot perform DH check\n");
}
if (codes) {
printf ("DH codes: %x\n", codes);
}
if (!DH_generate_key (dh_)) {
printf ("Failure in DH Generate key\n");
//retVal = false;
//break;
}
SSL_CTX_set_tmp_dh(ctx, dh_);
DH_free(dh_);
return ctx;
}
void ShowCerts(SSL *ssl) {
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
if (cert != NULL) {
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line); /* free the malloc'ed string */
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line); /* free the malloc'ed string */
X509_free(cert); /* free the malloc'ed certificate copy */
} else
printf("Info: No client certificates configured.\n");
}
int main(int count, char *strings[]) {
SSL_CTX *ctx;
int server;
SSL *ssl;
char buf[1024];
char acClientRequest[1024] = {0};
int bytes;
char *hostname, *portnum;
if (count != 3) {
printf("usage: %s <hostname> <portnum>\n", strings[0]);
exit(0);
}
SSL_library_init();
hostname = strings[1];
portnum = strings[2];
ctx = InitCTX();
server = OpenConnection(hostname, atoi(portnum));
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
printf ("Before connect\n");
if (SSL_connect(ssl) == FAIL) /* perform the connection */
ERR_print_errors_fp(stderr);
else {
char acUsername[16] = {0};
char acPassword[16] = {0};
const char *cpRequestMessage = "<Body>\
<UserName>%s<UserName>\
<Password>%s<Password>\
<\Body>";
printf("Enter the User Name : ");
scanf("%s", acUsername);
printf("\n\nEnter the Password : ");
scanf("%s", acPassword);
sprintf(acClientRequest, cpRequestMessage, acUsername,
acPassword); /* construct reply */
printf("\n\nConnected with %s encryption\n", SSL_get_cipher(ssl));
ShowCerts(ssl); /* get any certs */
SSL_write(ssl, acClientRequest,
strlen(acClientRequest)); /* encrypt & send message */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
buf[bytes] = 0;
printf("Received: \"%s\"\n", buf);
SSL_free(ssl); /* release connection state */
}
close(server); /* close socket */
SSL_CTX_free(ctx); /* release context */
return 0;
}
当我编译并执行此代码时,出现以下错误:
服务器端:
140093403805344:错误:140940E5:SSL例程:SSL3_READ_BYTES:ssl握手失败:s3_pkt.c:996:
客户端错误:
140134052299200:错误:141640B5:SSL例程:tls_construct_client_hello:无可用密码:../ ssl / statem / statem_clnt.c:800:
有什么可以帮助我建立与匿名DH的连接的信息吗?