2016-11-06 60 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

相關問題