2016-11-06 55 views
1

用Google搜索了很多,没有发现任何回答以下问题: 创建的服务器代码和客户端代码,但得到ssl_accept“没有共享密码”,为什么?

错误:1408A0C1:SSL例程:SSL3_GET_CLIENT_HELLO:没有共享密码

在服务器时做SSL_connect。

下面的代码被缩小到仅与SSL /套接字相关的函数调用的序列。在适用的情况下,应用错误处理代码以确保在SSL_accept/SSL_connect之前调用不会返回任何失败代码。我也遗漏了初始化方法。

我不知道它是否重要,但我在本地主机上运行服务器和客户端。

可能存在明显的错误,但我对OpenSSL颇为陌生。

客户端代码(inparams:主机名,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 
{ 
} 

Server代码(inparams: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 
} 

编辑: 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 

的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 

命令

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 

编辑2:与

ERR_load_crypto_strings();  // <<< To clarify my initialization (2) 
OpenSSL_add_all_ciphers();  // <<< To clarify my initialization (2) 

见顶部也试过。同样的结果。 “

”不幸的是,所有的初始化函数都返回一个无用的值(例如,总是1)或者是无效的函数,没有办法确定是否发生了故障“ - (https://wiki.openssl.org/index.php/Library_Initialization)太糟糕了!

回答

2

“no shared cipher” at ssl_accept, why?

可能有几个原因。以下是一些建议,具体取决于您遇到的问题。我怀疑一个或多个是你的问题的答案。


Client:

SSL_METHOD const * method = SSLv3_client_method(); 

和:

Server:

SSL_METHOD const * method = SSLv23_method(); 

你应该通过设置 “TLS 1.0及以上” 的开始。你可以在客户端和服务器上用下面的方法来做到这一点。它来自OpenSSL wiki和SLL/TLS Client示例。

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); 

您的客户还应该使用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_listSSL_set_cipher_list。它避免了来自浏览器的“Your connection to website is encrypted with obsolete cryptography”警告。

如果您正在使用椭圆曲线基于证书,那么你需要使用一个名为曲线。另请参阅Stack Overflow上的boost asio with ECDSA certificate issue和OpenSSL wiki上的Elliptic Curve Cryptography | Named Curves

确保您初始化OpenSSL库。如果磁带库没有正确初始化,那么将不会有密码,并且可能导致“没有共享密码”。另请参阅Stack Overflow上的Openssl SSL_CTX_new(SSLv3_method()) returns NULL和OpenSSL wiki上的Library Initialization

如果要创建自己的证书,请确保将主机名放在主题替代名称(SAN)中。主机名始终在SAN中。如果它存在于CN中,那么它也必须存在于SAN(在这种情况下,您必须列出它两次)。有关更多规则和原因,请参阅How do you sign Certificate Signing Request with your Certification AuthorityHow to create a self-signed certificate with openssl?

+0

我想关注http://stackoverflow.com/questions/21297139/how-do-you-sign-certificate-signing-request-with-your-certification-权限/ 21340898#21340898但使用以前创建的密钥,但提示不会返回。什么可能是错的?这里是我的命令: openssl req -config openssl-server-fromweb.cnf -out intermediate/certs/servercert.csr -outform PEM 。在conf文件中,在req下,我将default_keyfile设置为私钥的路径,并且它是有效的。 – Joachim

+0

我对提示没有任何建议。除非调用一些API,否则我从来没有见过OpenSSL API的提示。上述代码中没有任何内容。也许你应该问[Super User](http://superuser.com/)或[Unix&Linux Stack Exchange](http://unix.stackexchange.com/)中遇到的命令。 – jww

+0

好像添加-new -sha256让我回到提示。我用你的建议的结果更新了我的帖子。 – Joachim

相关问题