Joa*_*him 6 encryption openssl
用谷歌搜索了很多,没有找到以下问题的任何答案:创建服务器代码和客户端代码,但得到
错误:1408A0C1:SSL 例程:SSL3_GET_CLIENT_HELLO:无共享密码
在服务器上做SSL_connect。
下面的代码缩小到仅与 SSL/套接字相关的函数调用的顺序。错误处理代码已在适用的地方应用,以确保调用之前SSL_accept/SSL_connect不返回任何失败代码。我也省略了初始化方法。
我不知道这是否重要,但我在本地主机上同时运行服务器和客户端。
可能有明显的错误,但我对 OpenSSL 还很陌生。
客户端代码 (inparams: hostname, certificate_chain_file, ca_certificate_file):
SSL_library_init(); // <<< To clarify my initialization
OpenSSL_add_all_algorithms(); // <<< To clarify my initialization
SSL_load_error_strings(); // <<< To clarify my initialization
ERR_load_crypto_strings(); // <<< To clarify my initialization (2)
OpenSSL_add_all_ciphers(); // <<< To clarify my initialization (2)
SSL_METHOD const * method = SSLv23_method(); // <<< Updated method
SSL_CTX * ctx = SSL_CTX_new(method);
SSL_CTX_use_certificate_chain_file(ctx, certificate_chain_file));
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; // <<< Added
SSL_CTX_set_options(ctx, flags); // <<< Added
SSL_CTX_load_verify_locations(ctx, ca_certificate_file, NULL));
struct hostent * host = gethostbyname(hostname);
int client_sd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(6789);
server.sin_addr.s_addr = *(long *) (host->h_addr);
connect(client_sd, (struct sockaddr *) &server, sizeof(server));
SSL * ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_sd);
const char * const preferred_ciphers = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
SSL_set_cipher_list(ssl, preferred_ciphers); // <<< Added
SSL_set_tlsext_host_name(ssl, hostname); // <<< Added
mydata_t mydata;
mydata_index_client = SSL_get_ex_new_index(0, (void *) "mydata index", NULL, NULL, NULL);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback_client);
SSL_CTX_set_verify_depth(ctx, 1);
mydata.verify_depth = 0;
SSL_set_ex_data(ssl, mydata_index_client, &mydata);
int connection_result = SSL_connect(ssl);
if (connection_result < 0)
{
// Comes in here and ERR_get_error indicates
// error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
}
else if (connection_result == 0)
{
}
else if (connection_result == 1)
{
}
else
{
}
Run Code Online (Sandbox Code Playgroud)
服务器代码(输入参数:certificate_chain_file,ca_certificate_file):
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_METHOD const * method = SSLv23_method();
SSL_CTX * ctx = SSL_CTX_new(method);
SSL_CTX_use_certificate_chain_file(ctx, certificate_chain_file); //Contains only root CA
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) private_key_file_password);
SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
SSL_CTX_load_verify_locations(ctx, ca_certificate_file, NULL);
struct sockaddr_in addr;
int server_sd = create_socket(addr, 6789);
bind(server_sd, (struct sockaddr *) &addr, sizeof(addr));
listen(server_sd, max_nr_of_simultaneous_connections);
sockaddr_in client;
client.sin_family = AF_INET;
socklen_t c_len = sizeof(client);
int client_sd = accept(server_sd, (sockaddr *) &client, &c_len);
char remote_addr[INET_ADDRSTRLEN];
inet_ntop(client.sin_family, &(client.sin_addr), remote_addr, INET_ADDRSTRLEN);
SSL * ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_sd);
const char * const preferred_ciphers = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
SSL_set_cipher_list(ssl, preferred_ciphers); // <<< Added
STACK_OF(X509_NAME) * cert_names = SSL_load_client_CA_file(certificate_chain_file);
if (cert_names != NULL)
{
SSL_CTX_set_client_CA_list(ctx, cert_names);
}
mydata_t mydata;
mydata_index_server = SSL_get_ex_new_index(0, (void *) "mydata index", NULL, NULL, NULL);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback_server);
SSL_CTX_set_verify_depth(ctx, 1);
mydata.verify_depth = 1;
SSL_set_ex_data(ssl, mydata_index_server, &mydata);
int accept_result = SSL_accept(ssl);
if (accept_result == 0)
{
}
else if (accept_result < 0)
{
// Comes in here and ERR_get_error indicates
// error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher
}
Run Code Online (Sandbox Code Playgroud)
编辑: jww,我已经尝试了你在下面建议的东西。然而,没有任何进展;我仍然得到相同的错误输出。这是我创建证书的方式:
openssl-ca.cnf
HOME = .
RANDFILE = $ENV::HOME/.rnd
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
default_days = 1000 # how long to certify for
default_crl_days = 30 # how long before next CRL
default_md = sha256 # use public key default MD
preserve = no # keep passed DN ordering
x509_extensions = ca_extensions # The extensions to add to the cert
email_in_dn = no # Don't concat the email in the DN
copy_extensions = copy # Required to copy SANs from CSR to cert
base_dir = .
certificate = $base_dir/certs/ca_fromweb.cert.pem # The CA certifcate
private_key = $base_dir/private/ca.key.pem # The CA private key
new_certs_dir = $base_dir # Location for new certs after signing
database = $base_dir/index2.txt # Database index file
serial = $base_dir/serial2.txt # The current serial number
unique_subject = no # Set to 'no' to allow creation of
# several certificates with same subject.
####################################################################
[ req ]
default_bits = 4096
default_keyfile = ./private/ca.key.pem
distinguished_name = ca_distinguished_name
x509_extensions = ca_extensions
string_mask = utf8only
####################################################################
[ ca_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = SE
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Östergötland
localityName = Locality Name (eg, city)
localityName_default =
organizationName = Organization Name (eg, company)
organizationName_default =
organizationalUnitName = Organizational Unit (eg, division)
organizationalUnitName_default =
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default =
emailAddress = Email Address
emailAddress_default =
####################################################################
[ ca_extensions ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:true
keyUsage = keyCertSign, cRLSign
####################################################################
[ signing_policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ signing_req ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
Run Code Online (Sandbox Code Playgroud)
openssl-server.cnf
HOME = .
RANDFILE = $ENV::HOME/.rnd
####################################################################
[ req ]
default_bits = 2048
default_keyfile = ./intermediate/private/my.example.com.key.pem
distinguished_name = server_distinguished_name
req_extensions = server_req_extensions
string_mask = utf8only
####################################################################
[ server_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = SE
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Östergötland
localityName = Locality Name (eg, city)
localityName_default = Linköping
organizationName = Organization Name (eg, company)
organizationName_default =
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default =
emailAddress = Email Address
emailAddress_default =
####################################################################
[ server_req_extensions ]
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = @alternate_names
nsComment = "OpenSSL Generated Certificate"
####################################################################
[ alternate_names ]
DNS.1 = my.example.com
Run Code Online (Sandbox Code Playgroud)
命令
touch index.txt
echo 1000 > serial
openssl genrsa -aes256 -out ca.key.pem 4096
chmod 400 private/ca.key.pem
openssl req -config openssl-ca.cnf -key ca.key.pem -new -x509 -days 7300 -sha256 -extensions ca_extensions -out ca.cert.pem
chmod 444 ca.cert.pem
openssl genrsa -aes256 -out server.key.pem 4096
openssl req -config openssl-server.cnf -new -sha256 -key server.key.pem -out my.example.com.csr.pem
openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out my.example.com.cert.pem -infiles my.example.com.csr.pem
chmod 444 my.example.com.cert.pem
cat ca.cert.pem > ca_chain.cert.pem
Run Code Online (Sandbox Code Playgroud)
编辑2:也试过
ERR_load_crypto_strings(); // <<< To clarify my initialization (2)
OpenSSL_add_all_ciphers(); // <<< To clarify my initialization (2)
Run Code Online (Sandbox Code Playgroud)
见上。结果一样。
“不幸的是,所有的初始化函数都返回一个无用的值(例如,总是 1)或者是空函数。没有办法确定是否发生了故障。” - ( https://wiki.openssl.org/index.php /Library_Initialization )太糟糕了!
ssl_accept 上的“无共享密码”,为什么?
可能有几个原因。以下是一些建议,具体取决于您遇到的问题。我怀疑一个或多个是您问题的答案。
客户:
Run Code Online (Sandbox Code Playgroud)SSL_METHOD const * method = SSLv3_client_method();
和:
服务器:
Run Code Online (Sandbox Code Playgroud)SSL_METHOD const * method = SSLv23_method();
您应该从设置“TLS 1.0 及更高版本”开始。您可以使用以下方法在客户端和服务器上执行此操作。它来自 OpenSSL wiki 和SLL/TLS 客户端示例。
const SSL_METHOD* method = SSLv23_method();
if(method == NULL) handleFailure();
ctx = SSL_CTX_new(method);
if(ctx == NULL) handleFailure();
...
/* Cannot fail ??? */
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);
Run Code Online (Sandbox Code Playgroud)
您的客户端还应使用Server Name Indication (SNI)。客户端将它与SSL_set_tlsext_host_name. SNI 是 TLS 扩展,这也是您想要“TLS 1.0 及更高版本”的部分原因。
客户端和服务器都希望使用像"HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4". 使用SSL_CTX_set_cipher_list或设置它们SSL_set_cipher_list。它避免了来自浏览器的“您与网站的连接已使用过时的加密技术加密”警告。
如果您使用的是基于椭圆曲线的证书,则需要使用命名曲线。另请参阅有关 Stack Overflow 和椭圆曲线密码学的带有 ECDSA 证书问题的 boost asio | OpenSSL wiki 上的命名曲线。
确保初始化 OpenSSL 库。如果库没有正确初始化,那么将没有可用的密码,并且可能导致“没有共享密码”。另请参阅OpenSSL wiki 上的Openssl SSL_CTX_new(SSLv3_method()) 返回 NULL堆栈溢出和库初始化。
如果您要创建自己的证书,请确保将主机名放在主题备用名称 (SAN) 中。主机名总是在SAN 中。如果它存在于CN 中,那么它也必须存在于SAN 中(在这种情况下,您必须将其列出两次)。有关更多规则和原因,请参阅如何使用证书颁发机构签署证书签名请求和如何使用 openssl 创建自签名证书?
一些较旧的 OpenSSL 版本(例如 RHEL 7.x 中的版本)需要在初始化阶段显式调用SSL_CTX_set_ecdh_auto()以启用高级算法的协商。请参阅https://wiki.openssl.org/index.php/Simple_TLS_Server
| 归档时间: |
|
| 查看次数: |
32310 次 |
| 最近记录: |