我想用密码EDH-RSA-DES-CBC3-SHA测试TLS 1.0连接。
我使用openssl s_server和s_client进行测试。工作良好。连接和数据交换都很好。
openssl s_server -accept 4433 -cert server.pem -key serverkey.pem -cipher EDH-RSA-DES-CBC3-SHA -tls1
openssl s_client -connect 127.0.0.1:443 -cipher EDH-RSA-DES-CBC3-SHA -tls1
共享密码:EDH-RSA-DES-CBC3-SHA
现在,我有另一个简单的OpenSSL服务器代码。使用this和s_client,连接失败,服务器抛出以下内容:
3077613304:错误:1408A0C1:SSL例程:SSL3_GET_CLIENT_HELLO:无共享密码:s3_srvr.c:1361
我检查s_server / s_client使用的库和我的服务器应用程序使用的库是否相同如下:
cat /proc/9515/maps | awk '{print $6}' | grep '\.so' | sort | uniq | grep -e ssl -e libcrypto
/usr/lib/libcrypto.so.1.0.1e
/usr/lib/libssl.so.1.0.1e
但是,对于像AES128-SHA这样的其他密码的,从s_client到我的服务器应用程序的连接都没问题。
以下是我在服务器代码中设置ctx
的方法:
SSL_CTX* InitServerCTX(void)
{
SSL_CTX *ctx = NULL;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(TLSv1_server_method());
SSL_CTX_set_cipher_list(ctx,"EDH-RSA-DES-CBC3-SHA"); // Returns 1
SSL_CTX_use_certificate_chain_file(ctx, "server.pem");
SSL_CTX_use_PrivateKey_file(ctx, "serverkey.pem", SSL_FILETYPE_PEM);
return ctx;
}
为什么我的服务器应用程序会出现'没有共享密码'错误和s_server对同一个客户端没问题?
答案 0 :(得分:4)
@ Cmidid的回答是正确的。这里有更多信息,包括IETF DH组和通过DH回调选择组大小。
用C ++编写,但很容易转换回C。
using DH_ptr = std::unique_ptr<DH, decltype(&::DH_free)>;
using BIO_MEM_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
using BIO_FILE_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
using SSL_CTX_ptr = std::unique_ptr<SSL_CTX, decltype(&::SSL_CTX_free)>;
SSL_CTX* CreateServerContext(const string & domain)
{
const SSL_METHOD* method = SSLv23_server_method();
ASSERT(method != NULL);
SSL_CTX_ptr t(SSL_CTX_new(method), ::SSL_CTX_free);
ASSERT(t.get() != NULL);
long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
flags |= SSL_OP_NO_COMPRESSION;
flags |= SSL_OP_SAFARI_ECDHE_ECDSA_BUG;
flags |= SSL_OP_CIPHER_SERVER_PREFERENCE;
SSL_CTX_set_options(t.get(), flags);
string ciphers = "HIGH:!aNULL:!RC4:!MD5";
rc = SSL_CTX_set_cipher_list(t.get(), ciphers.c_str());
...
LogDebug("GetServerContext: setting DH callback");
SSL_CTX_set_tmp_dh_callback(t.get(), DhCallback);
LogDebug("GetServerContext: setting ECDH callback");
SSL_CTX_set_tmp_ecdh_callback(t.get(), EcdhCallback);
...
return t.release();
}
DH* DhCallback(SSL *ssl, int is_export, int keylength)
{
UNUSED(ssl);
UNUSED(is_export);
#if defined(ALLOW_DH_1024_PARAMS)
if (keylength <= 1024 + 4)
return DH1024();
else
#endif
if (keylength <= 1536 + 4)
return DH1536();
else if (keylength <= 2048 + 4)
return DH2048();
else if (keylength <= 3072 + 4)
return DH3072();
else if (keylength <= 4096 + 4)
return DH4096();
return DH4096();
}
#if defined(ALLOW_DH_1024_PARAMS)
static DH* DH1024()
{
static const char g_dh1024_sz[] = "-----BEGIN DH PARAMETERS-----\n"
"MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n"
"Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n"
"/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC\n"
"-----END DH PARAMETERS-----";
static DH_ptr dh(NULL, NULL);
if (dh.get())
return dh.get();
BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh1024_sz, (int) sizeof(g_dh1024_sz)), ::BIO_free);
ASSERT(bio.get());
dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
unsigned long err = ERR_get_error();
ASSERT(dh.get());
return dh.get();
}
#endif
static DH* DH1536()
{
static const char g_dh1536_sz[] = "-----BEGIN DH PARAMETERS-----\n"
"MIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n"
"Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n"
"/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORbPcIAfLihY78FmNpINhxV05pp\n"
"Fj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaWbWcMNU5KvJgE8XRsCMojcyf/\n"
"/////////wIBAg==\n"
"-----END DH PARAMETERS-----";
static DH_ptr dh(NULL, NULL);
if (dh.get())
return dh.get();
BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh1536_sz, (int) sizeof(g_dh1536_sz)), ::BIO_free);
ASSERT(bio.get());
dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
unsigned long err = ERR_get_error();
ASSERT(dh.get());
return dh.get();
}
static DH* DH2048()
{
static const char g_dh2048_sz[] = "-----BEGIN DH PARAMETERS-----\n"
"MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n"
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n"
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n"
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n"
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n"
"5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n"
"-----END DH PARAMETERS-----";
static DH_ptr dh(NULL, NULL);
if (dh.get())
return dh.get();
BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh2048_sz, (int) sizeof(g_dh2048_sz)), ::BIO_free);
ASSERT(bio.get());
dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
unsigned long err = ERR_get_error();
ASSERT(dh.get());
return dh.get();
}
static DH* DH3072()
{
static const char g_dh3072_sz[] = "-----BEGIN DH PARAMETERS-----\n"
"MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n"
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n"
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n"
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n"
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n"
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n"
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n"
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS\n"
"yv//////////AgEC\n"
"-----END DH PARAMETERS-----";
static DH_ptr dh(NULL, NULL);
if (dh.get())
return dh.get();
BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh3072_sz, (int) sizeof(g_dh3072_sz)), ::BIO_free);
ASSERT(bio.get());
dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
unsigned long err = ERR_get_error();
ASSERT(dh.get());
return dh.get();
}
static DH* DH4096()
{
static const char g_dh4096_sz[] = "-----BEGIN DH PARAMETERS-----\n"
"MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n"
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n"
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n"
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n"
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n"
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n"
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n"
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI\n"
"ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O\n"
"+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI\n"
"HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI=\n"
"-----END DH PARAMETERS-----";
static DH_ptr dh(NULL, NULL);
if (dh.get())
return dh.get();
BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh4096_sz, (int) sizeof(g_dh4096_sz)), ::BIO_free);
ASSERT(bio.get());
dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
unsigned long err = ERR_get_error();
ASSERT(dh.get());
return dh.get();
}
答案 1 :(得分:2)
您需要创建一个DH对象并为ssl context DH
设置ctx
参数。更具体地说,一旦分配了DH对象,就需要设置primp p和generator g。
这样做的一种方法是使用下面的示例伪代码
这里dh512_p
dh512_g
分别是primo p和generator g
DH* get_dh512(const unsigned char *dh512_p,const unsigned char *dh512_g)
{
DH *dh=NULL;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
return(NULL);
return(dh);
}
然后使用回调
在函数中设置参数//if key exchange is based on diffie hellman
DH *dh = get_dh512(dh512_p,dh512_g)
SSL_CTX_set_tmp_dh(ctx,dh);
SSL_CTX_set_cipher_list(ctx,ciphers);
请查看以下链接,了解回拨详情http://linux.die.net/man/3/ssl_ctx_set_tmp_dh