该公司需要在Windows平台上实现Web小程序. Web小程序具有以下要求:
体积小,无需安装10M以下的文件,下载它,双击以使用https加密即可与浏览器通信
为了实施此小程序,该公司选择了以下技术:
使用猫鼬框架并使用openssl库以https加密在C语言中编写. SSL证书存储在字符串中c web后台输出字符串,而不存储在文件中.
注意: ssl证书没有存储在文件中,而是存储在字符串中,因为不需要安装applet. 只有一个exe文件,没有其他文件.
该公司使用猫鼬框架作为Web服务器. 猫鼬非常轻巧. github地址是: github.com/cesanta/mongoose. 目前它有超过5k颗恒星,并且相对稳定.

麻烦的实现是SSL证书没有存储在文件中c web后台输出字符串,而是存储在字符串中. 猫鼬对https的实现是基于证书的文件,因此需要修改相关代码.
干货直接装在下面. 修改后的函数主要是mongoose.c文件中的mg_use_cert函数.
static enum mg_ssl_if_result mg_use_cert(SSL_CTX *ctx, const char *cert,
const char *key,
const char **err_msg) {
if (key == NULL) key = cert;
if (cert == NULL || cert[0] == '\0' || key == NULL || key[0] == '\0') {
return MG_SSL_OK;
} else if (SSL_CTX_use_certificate_file(ctx, cert, 1) == 0) {
MG_SET_PTRPTR(err_msg, "Invalid SSL cert");
return MG_SSL_ERROR;
} else if (SSL_CTX_use_PrivateKey_file(ctx, key, 1) == 0) {
MG_SET_PTRPTR(err_msg, "Invalid SSL key");
return MG_SSL_ERROR;
} else if (SSL_CTX_use_certificate_chain_file(ctx, cert) == 0) {
MG_SET_PTRPTR(err_msg, "Invalid CA bundle");
return MG_SSL_ERROR;
} else {
SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#if !MG_DISABLE_PFS && !defined(KR_VERSION)
BIO *bio = NULL;
DH *dh = NULL;
/* Try to read DH parameters from the cert/key file. */
bio = BIO_new_file(cert, "r");
if (bio != NULL) {
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
}
/*
* If there are no DH params in the file, fall back to hard-coded ones.
* Not ideal, but better than nothing.
*/
if (dh == NULL) {
bio = BIO_new_mem_buf((void *) mg_s_default_dh_params, -1);
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
}
if (dh != NULL) {
SSL_CTX_set_tmp_dh(ctx, dh);
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
DH_free(dh);
}
#if OPENSSL_VERSION_NUMBER > 0x10002000L
SSL_CTX_set_ecdh_auto(ctx, 1);
#endif
#endif
}
return MG_SSL_OK;
}

直接修改修改后的代码,主要思路是:
用功能SSL_CTX_use_certificate_file替换SSL_CTX_use_certificate_file用PEM_read_bio_RSAPrivateKey替换SSL_CTX_use_PrivateKey_file. 将SSL_CTX_use_certificate_chain_file替换为X509_STORE_add_cert函数
具体代码如下:

static int mg_use_cert(SSL_CTX *ctx, const char *cert, const char *key) {
if (ctx == NULL) {
return -1;
} else {
int ret = 0;
#if 0
if (SSL_CTX_use_certificate_file(ctx, cert, 1) == 0) {
return -2;
}
if (SSL_CTX_use_PrivateKey_file(ctx, key, 1) == 0) {
return -2;
}
#endif
/* 使用函数SSL_CTX_use_certificate 替换SSL_CTX_use_certificate_file
* 创建BIO结构,存储pem字符串内容,pem字符串内容存储在fangstarHelperPem字符数组中
* fangstarHelperPem的存储见第四节:字符串存储ssl证书
*/
BIO *cbio = BIO_new(BIO_s_mem());
BIO_puts(cbio, fangstarHelperPem);
X509* xCert = NULL;
xCert = PEM_read_bio_X509(cbio, NULL, 0, NULL);
ret = SSL_CTX_use_certificate(ctx, xCert);
BIO_free(cbio);
if (ret != 1) {
printf("Failed to use cretificate\n");
return -2;
}
/* 使用PEM_read_bio_RSAPrivateKey 替换SSL_CTX_use_PrivateKey_file.
* 创建BIO结构,存储key字符串内容,key字符串内容存储在fangstarHelperKey字符数组中
* fangstarHelperKey的存储见第下一节:字符串存储ssl证书
*/
BIO *kbio = BIO_new(BIO_s_mem());
BIO_puts(kbio, fangstarHelperKey);
RSA *rsa = PEM_read_bio_RSAPrivateKey(kbio, NULL, 0, NULL);
BIO_free(kbio);
ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
if (ret != 1) {
printf("Failed to use RSA Private Key\n");
return -2;
}
if (!SSL_CTX_check_private_key(ctx)) {
printf("Failed to check RSA Private Key\n");
return -2;
}
#ifndef MG_DISABLE_PFS
BIO *bio = NULL;
DH *dh = NULL;
/* Try to read DH parameters from the cert/key file. */
//bio = BIO_new_file(cert, "r");
bio = BIO_new(BIO_s_mem());
BIO_puts(bio, fangstarHelperPem);
//bio = BIO_new_mem_buf(fangstarHelperPem, sizeof(fangstarHelperPem));
if (bio != NULL) {
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
}
/*
* If there are no DH params in the file, fall back to hard-coded ones.
* Not ideal, but better than nothing.
*/
if (dh == NULL) {
bio = BIO_new_mem_buf((void *) mg_s_default_dh_params, -1);
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
}
if (dh != NULL) {
SSL_CTX_set_tmp_dh(ctx, dh);
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
DH_free(dh);
}
#endif
SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
//SSL_CTX_use_certificate_chain_file(ctx, cert);
/* 使用X509_STORE_add_cert函数替换SSL_CTX_use_certificate_chain_file来添加cert证书 */
BIO *chainBio = BIO_new(BIO_s_mem());
BIO_puts(chainBio, fangstarHelperPem);
X509* chainCert = NULL;
while (chainCert = PEM_read_bio_X509(chainBio, NULL, 0, NULL)) {
X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), chainCert);
}
BIO_free(chainBio);
return 0;
}
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-153279-1.html
美国还没有把最新的伯克级派过来