EmbedTLS + Eclipse C/C++测试用例SSL客户端和服务器

目录

  • EmbedTLS + Eclipse C/C++测试用例SSL客户端和服务器
    • (1)说明
    • (2)Eclipse的embedtls移植
    • (3)OpenSSL公私钥及证书生成
    • (4)测试
      • embedtls认证模式说明
      • embedtls单向认证设置
      • embedtlss双向认证设置:
      • 代码示例
        • 1、客户端代码模型
        • 2、服务器代码模型

(1)说明

STM32移植使用mbedtls-2.24.0点这里:https://blog.csdn.net/qq153471503/article/details/109461794

mbedtls下载地址:https://github.com/ARMmbed/mbedtls

embedtls的ssl示例代码在这里可以找到:https://github.com/ARMmbed/mbedtls/tree/development/programs/ssl


(2)Eclipse的embedtls移植

我是用的是Eclipse C/C++和MinGW编译工具链,embedtls移植很简单,只需要把源码目录下的include和library文件夹拷贝到工程目录下即可,如下图:

然后右键工程->Properties->C/C++ Build->Settings->Tool Sttings->GCC C Compiler->Include添加头文件包含,如下图:

然后使用C99语法编译规则:

因为mingw使用的标准系统调用,在win上就得链接windows系统的库,所以还需要添加一个链接标记:


(3)OpenSSL公私钥及证书生成

点这里:https://blog.csdn.net/qq153471503/article/details/109524764


(4)测试

embedtls认证模式说明

  • MBEDTLS_SSL_VERIFY_NONE:不检查对等证书(也就是无认证)。(服务器默认值,如果客户端配置为此选项那么连接是不安全的;如果服务器配置为此值那么是单向认证。

  • MBEDTLS_SSL_VERIFY_OPTIONAL :检查对等证书(也就是单向认证),但即使验证失败,握手仍将继续;可以在握手完成后调用mbedtls_ssl_get_verify_result()查看验证结果。

  • MBEDTLS_SSL_VERIFY_REQUIRED :客户端服务器必须同时出示有效证书(也就是双向认证),如果验证失败,握手将终止。(客户端默认值)

embedtls单向认证设置

  • 服务器认证模式设置:MBEDTLS_SSL_VERIFY_OPTIONAL、MBEDTLS_SSL_VERIFY_NONE。如果服务器设置为MBEDTLS_SSL_VERIFY_NONE,不管客户端设置什么属性,在握手时候都不会对证书进行认证;如果设置为MBEDTLS_SSL_VERIFY_OPTIONAL,那么进行单向认证,验证失败的话,通信仍然有效。

  • 客户端认证模式设置:根据需求可选择MBEDTLS_SSL_VERIFY_NONE(不认证)、MBEDTLS_SSL_VERIFY_OPTIONAL(验证若失败也会继续保持通信)、MBEDTLS_SSL_VERIFY_REQUIRED(验证失败将终止连接)。

embedtlss双向认证设置:

  • 服务器设置为MBEDTLS_SSL_VERIFY_REQUIRED

  • 客户端根据安全需求选择MBEDTLS_SSL_VERIFY_NONE(不检查)、MBEDTLS_SSL_VERIFY_OPTIONAL(验证但是验证失败通信仍有效)、MBEDTLS_SSL_VERIFY_REQUIRED(验证失败通信无效)

在代码中这个宏定义控制着是否加载服务器的证书和密钥,如果是单向认证,客户端是不需要加载服务器的证书和密钥的,当然加载上也不影响。

代码示例

1、客户端代码模型

/** main.c**  Created on: 2020年10月29日*      Author: hello*/#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mbedtls/config.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/certs.h"#define debug_e(fmt, ...) do{fprintf(stderr, fmt, ##__VA_ARGS__);fflush(stderr);}while(0);
#define debug(fmt, ...)   do{printf(fmt, ##__VA_ARGS__);fflush(stdout);}while(0);unsigned char mbedtls_ca_crt[] =
{"-----BEGIN CERTIFICATE-----\r\n"                                      \"MIIDPTCCAiUCFAyaaimE7qW89Z0Verz2WN3cABu4MA0GCSqGSIb3DQEBCwUAMFox\r\n" \"CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoM\r\n" \"BFFEWlkxFTATBgNVBAsMDHd3dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwIBcNMjAx\r\n" \"MTA1MDgxOTM0WhgPMjEyMDEwMTIwODE5MzRaMFoxCzAJBgNVBAYTAkNOMQswCQYD\r\n" \"VQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoMBFFEWlkxFTATBgNVBAsMDHd3\r\n" \"dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\r\n" \"ggEKAoIBAQDWU0v4jZ1OPxpGJT8kGKer3tWtLE8Lc7DdDIiikerznKsBXtjxMjZH\r\n" \"+HlEjf/dp5LqQhsEfVQa7+YXJGVmdXvTpGrIkP0YiAlQscdgmFkoRcyEVJY/oCgE\r\n" \"BhIKh68otjZkVgK/E4qzpv2C6575iR4WxJG01LAVzdRvDPYyK08aXfKgTxygxJOC\r\n" \"40iQicOVZ8/s9iBfPxXXPaYf5tOf9nGi4fOba8eGa32ZtpJCBHS45Z5JYAWSM2aW\r\n" \"s9O7WQRvehw4eOza5gtw/+SlKHB4SlguwNBxz+kMS6t5PN16GPZW+vsY4aVSaXw6\r\n" \"5z2fZTTtvFoUT0j40fRF8N1BPV5ubZr5AgMBAAEwDQYJKoZIhvcNAQELBQADggEB\r\n" \"AK+6MRg6U7cT2fFsKRlhYGB1Q7pY8jn8RmdEOHwfbEFiW1as2DantVs1S8ZWgIL8\r\n" \"+gu0FlNC1QlPOVceF2SCl/44dtgXSSGqivZfnK9v8Gg7HMQMSgXtQlULu4piVpVw\r\n" \"pi3HkzIBsQiHtBaLB7ukmOmFXFXorrHbVxsIK9ZZW+OAP+E8O0byEVkyUMCLugxd\r\n" \"B8IQiGN0SmIOIuM5VoRujnLBBs8GCY+XmEf3qgHU+Tv5I6IhSL+p0eTfVP17ZFU4\r\n" \"a6xkq64n74XDOKlpIEQ9NnHpHiQmCYkMBZwC2NBNXKG/uw5PKkV51kFqaHe8T29n\r\n" \"4uhXD15/+AkOnvhSt7Uuooc=\r\n"                                         \"-----END CERTIFICATE-----\r\n"
};unsigned char mbedtls_client_crt[] =
{"-----BEGIN CERTIFICATE-----\r\n" \"MIIDYDCCAkgCFG2ck7C9+1Hyz/ipV3TxBxUYfvHdMA0GCSqGSIb3DQEBCwUAMFox\r\n" \"CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoM\r\n" \"BFFEWlkxFTATBgNVBAsMDHd3dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwIBcNMjAx\r\n" \"MTA2MDUzNjM2WhgPMjEyMDEwMTMwNTM2MzZaMH0xCzAJBgNVBAYTAkNOMQswCQYD\r\n" \"VQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoMBFFEWlkxFTATBgNVBAsMDHd3\r\n" \"dy50ZXN0LmNvbTEPMA0GA1UEAwwGQ0xJRU5UMR0wGwYJKoZIhvcNAQkBFg5hZG1p\r\n" \"bkB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK/MX5t+\r\n" \"FU6de4bgZer45C5CjkwtbS7nSdBiMmZSbN4NRHDqhsBTnqK4W2TkYxKjY+YOos5S\r\n" \"LCN/gaRY1SANJ10Ohdvyr+GJBv/MKPdCWA0MScCUT9B+ihgX4MhBLwz0SNnlcT97\r\n" \"zA5owB6ynj/hY26foOto9eFVRVl1tUaXm94g6JcMZdI7/ie0KtzMLb0vnSII5eXk\r\n" \"61vRQ03XOh9D3iiYQ6CfYLwC7NA2i2fYi7mFCGhFJyUIgZSF70Qd5lzd2bYZEfYr\r\n" \"zZs7m4TZ60Gs78meystKN1AxtPHTMhW3tjekWIqvbVWE2H+QQwWosmOovRr1dNDh\r\n" \"h+JNJZeNJAY7rHMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAZnoOOJfqLVxYLKrQ\r\n" \"o9nlhHmN+Fh/8Gs+gECocg0f4Yj+XFHnwGut3M79aPHGgNLt62sIK03tAPzjBh89\r\n" \"+PLMsM80nh17AgE5xNEJUl2jxOzwAKMuBILgP9IAXSTqAs+xEd7ZJki0eiNXIAoV\r\n" \"GJgsXxL7MoXMO/x6B5inwIIhbaPdC2VzHC/SV5V1HvGVV/OJnJuLwemjCaJTEcaZ\r\n" \"x9JVlal7CXk8W8DeSz+PgrdFwdnT0NU+KGFuW5hCZHdsASYtURsdpO9jYFBxQdsF\r\n" \"jMGWYZbUH6t5hHVfjp/lLPxGHvqR90EcYS+PwWzNSw2IACw2EnyvDYZwzmUM9J9g\r\n" \"Ak7ypg==\r\n" \"-----END CERTIFICATE-----\r\n"
};unsigned char mbedtls_client_key[] =
{"-----BEGIN RSA PRIVATE KEY-----\r\n"                                  \"Proc-Type: 4,ENCRYPTED\r\n"                                           \"DEK-Info: AES-256-CBC,784C65C31E5AB3918DD25BC12DF00B4B\r\n"           \"\r\n"                                                                 \"R3IW5IZg7ClBUiPec7wTdjBBs6WSWLacnThO/3X77kY3OzEApIpQq8RVS8oiMZB7\r\n" \"N7Q65KTP1TOCZl/AWiiGcW0RCUAeuVM9cWw4GqfEYk0l1x7OWdc8AZu11FJ8WcUy\r\n" \"BJDgv1h1fY+XzM4+cgDUUzHOJt9QHjQ6iEaheisqeHIZkHfRYqR8kNQOBi1280tL\r\n" \"9lO8Ns75py9YvkPWHT9lUy1T3avJeuoU7JiL1v4iUHW9wUi1NuPwxamoDjrtwUtJ\r\n" \"zi0vy8/Xs4x38gLT0fv1UIvD1yS7W1R+c5melHkLYboPUg8i5azuSLYXSD0yIHh/\r\n" \"Xhb2AhpQF6PuGdapR1+tMne6pP2+rI3B9J9bPwfMN0m/SBy4me9McYfLs08dsmuz\r\n" \"eLGwwcLWQDtigCjFshTwhXVeStS0vVDEJmLGMOPiLtXFNdPyZthdI/QvJVlLAOXS\r\n" \"76Q4mKzczWBqWRDLknkKxq5fgGqvXkiIRgecXNTkFanVebIT74O8egWvTQT6CSQ6\r\n" \"TYckto3rBw+5MCM0wlhEh+5CgDJ3+1UsQkeqAizz3We/p0qTKR+0bwnm9HO8V3MW\r\n" \"62QmPzLEzdDvPSLxjSOT61Qe5LxQMyhvRw9JXl1flcJex/PLCZIu9/Qn/QlM9oyU\r\n" \"rspMDEJH9nVI8VyE94krwvCQYJ163bRRvraj/zQ8hPaCnpMuORYbBl1BG1e6DeHH\r\n" \"o++DtJ1aEPF2M8QNIORi5YQKfgcfqzEMMULw8ZoToomEIj3Mox/gL3idB9YYX5o+\r\n" \"GgerK6mjNkbAErpcf5XQG8jKdaQILp/JyUy8a+HdP7oFUr9Sc7Wr+Kg0KqVnlhMM\r\n" \"w09U3xHAcbc4yuRK7inozGixWEBvXlb4e7SEAg2Jeh6gjDEBWOCDQR09FXmkZw/I\r\n" \"dY484u0r/Uikme39IXVtPE8ovaNUjLrTf8pcKgZiRg51+k/xoRJXRmUTFc2pE67g\r\n" \"niy4JhdG1bd1SWy3AYfVSd6aST/VJGjxxu71qg6LPAzu7S9ihuRQNaiEabk+O34x\r\n" \"cHKbD7QO0O4ke/1wCeJFmcVEFHxrscoQM7g2TD5T4F0lA+c+D/jDq/LIOLvHIWSb\r\n" \"CAXnOsJd0vxg99IBZV+9IqvIiWuxh0Aian1XUxaQU/Uc0qE9h/JL2wxMLgG9CVxU\r\n" \"U2KdbcBLnq3/UqFDr536ANufJss/9eccowT/jr3vwoIfnRMYyp++D6XfmZqWlPuF\r\n" \"SKw20WGADuAl1vHYdDbaPBbH2IkvIRwO/tjCG16D/I1KnAZcMIAPSAzDIi9vhvfS\r\n" \"w2YXgTXJ3jXzJ7T30pc+0GVFckVqivMDNyq0kIWOR47CrL5dBub/KZyIBtKASHMe\r\n" \"AguG7jvtz/3zIVdVJwGc31MxPrtINf0A33IGOx/uwzlcxOChwKNeRn63IGLU3rqW\r\n" \"0xWpYNeeL/YKxKYttnpw3JQ0/8J2TrGvMg7hWLKl1rCXdIqAaz1ZmlczDRLbznCl\r\n" \"dNBKN67zwe/YqyGAoi6jfvIEHs7k7JPQQhwbDlY9XzEDAvc5kNQ4BToeDf8DFW+N\r\n" \"wvbgXy04sFIXOYCCkgEcrqOURMTU8dQ+/gSqAnMdFE1CbZSELQVe9pcO8ea3Usis\r\n" \"-----END RSA PRIVATE KEY-----\r\n"                                    \
};typedef struct
{mbedtls_net_context netctx;mbedtls_ssl_context sslctx;mbedtls_ssl_config sslcfg;mbedtls_ctr_drbg_context drbgctx;mbedtls_entropy_context etpyctx;mbedtls_x509_crt x509cacrt;mbedtls_x509_crt x509clicrt;mbedtls_pk_context pkey;
}mbedtls_client_t;size_t mbedtls_client_key_len = sizeof(mbedtls_client_key);
size_t mbedtls_client_crt_len = sizeof(mbedtls_client_crt);
size_t mbedtls_ca_crt_len = sizeof(mbedtls_ca_crt);unsigned char Buffer[1024];
mbedtls_client_t client;#define IP "192.168.31.16"
#define PORT "5004"mbedtls_x509_crt_profile x509_crt_profile =
{MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),0xFFFFFFF, /* Any PK alg    */0xFFFFFFF, /* Any curve     */2048,      /* 密钥长度为2048 */
};static int mbedtls_ssl_sig_hashes[] =
{MBEDTLS_MD_SHA512,MBEDTLS_MD_SHA384,MBEDTLS_MD_SHA256,MBEDTLS_MD_SHA224,MBEDTLS_MD_SHA1,MBEDTLS_MD_NONE
};int mbedtls_ssl_client_init(mbedtls_client_t* client,const void* cacert, size_t cacertLength,const void* clicert,size_t clicertLength,const void* clikey, size_t clikeyLength,const void* clipwd, size_t clipwdLength,const void* pers,   size_t persLength,const void* CNname)
{int ret = 0;//// 初始化//mbedtls_net_init(&client->netctx);mbedtls_ssl_init(&client->sslctx);mbedtls_ssl_config_init(&client->sslcfg);mbedtls_ctr_drbg_init(&client->drbgctx);mbedtls_x509_crt_init(&client->x509cacrt);mbedtls_x509_crt_init(&client->x509clicrt);mbedtls_pk_init(&client->pkey);mbedtls_entropy_init(&client->etpyctx);// 加载CA证书if((ret = mbedtls_x509_crt_parse(&client->x509cacrt, (const unsigned char *)cacert, cacertLength)) != 0)return -1;if(clicert != NULL){// 加载客户端证书if((ret = mbedtls_x509_crt_parse(&client->x509clicrt, (const unsigned char *)clicert, clicertLength)) != 0)return -2;// 加载服务器密钥if((ret = mbedtls_pk_parse_key(&client->pkey, (const unsigned char *) clikey, clikeyLength, (const unsigned char *)clipwd, clipwdLength)) != 0)return -3;// 设置客户端证书和密钥关联if ((ret = mbedtls_ssl_conf_own_cert(&client->sslcfg, &client->x509clicrt, &client->pkey)) != 0)return -4;}// 设置SSL/TLS熵源if((ret = mbedtls_ctr_drbg_seed(&client->drbgctx, mbedtls_entropy_func, &client->etpyctx, (const unsigned char *)pers, persLength)) != 0)return -5;// 设置SSL为客户端ret = mbedtls_ssl_config_defaults(&client->sslcfg, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);if(ret != 0)return -6;// 设置用于验证的X.509安全配置文件mbedtls_ssl_conf_cert_profile(&client->sslcfg, &x509_crt_profile);// 设置握手签名的允许/首选散列算法mbedtls_ssl_conf_sig_hashes(&client->sslcfg, mbedtls_ssl_sig_hashes);//// 设置认证模式//// MBEDTLS_SSL_VERIFY_NONE     :不检查对等证书(服务器默认值)。如果客户端配置为此选项那么连接是不安全的。//// MBEDTLS_SSL_VERIFY_OPTIONAL :检查对等证书,但即使验证失败,握手仍将继续;//                               可以在握手完成后调用mbedtls_ssl_get_verify_result()查看验证结果。//// MBEDTLS_SSL_VERIFY_REQUIRED :同时必须出示有效证书,如果验证失败,握手将终止。(客户端默认值)//mbedtls_ssl_conf_authmode(&client->sslcfg, MBEDTLS_SSL_VERIFY_REQUIRED);// 设置随机数生成器回调mbedtls_ssl_conf_rng(&client->sslcfg, mbedtls_ctr_drbg_random, &client->drbgctx);// 设置CA证书mbedtls_ssl_conf_ca_chain(&client->sslcfg, &client->x509cacrt, NULL);// 配置设置if((ret = mbedtls_ssl_setup(&client->sslctx, &client->sslcfg)) != 0)return -7;// 设置SSL服务器CN名称if((ret = mbedtls_ssl_set_hostname(&client->sslctx, (const char *)CNname)) != 0)return -8;return 0;
}int mbedtls_ssl_client_connect(mbedtls_client_t* client,const void* ip, const void* port)
{int ret = 0;// 重置客户端连接mbedtls_net_free(&client->netctx);// 重置SSL会话信息mbedtls_ssl_session_reset(&client->sslctx);// 连接到服务器if((ret = mbedtls_net_connect(&client->netctx, (const char *)ip, (const char *)port, MBEDTLS_NET_PROTO_TCP)) != 0)return -1;// 设置数据接收发送回调mbedtls_ssl_set_bio(&client->sslctx,&client->netctx,mbedtls_net_send,mbedtls_net_recv,mbedtls_net_recv_timeout);// 握手while((ret = mbedtls_ssl_handshake(&client->sslctx)) != 0){if((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE))return -2;}// 获取验证结果if((ret = mbedtls_ssl_get_verify_result(&client->sslctx)) != 0){char vrfy_buf[128];int flags = mbedtls_ssl_get_verify_result(&client->sslctx);mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", flags );debug_e( "%s\n", vrfy_buf );
//      return -3;}return 0;
}void mbedtls_ssl_client_destory(mbedtls_client_t* client)
{mbedtls_net_free(&client->netctx);mbedtls_x509_crt_free(&client->x509cacrt);mbedtls_x509_crt_free(&client->x509clicrt);mbedtls_pk_free(&client->pkey);mbedtls_ssl_free(&client->sslctx);mbedtls_ssl_config_free(&client->sslcfg);mbedtls_ctr_drbg_free(&client->drbgctx);mbedtls_entropy_free(&client->etpyctx);
}void mbedtls_ssl_client_disconnect(mbedtls_client_t* client)
{mbedtls_ssl_close_notify(&client->sslctx);
}#define AUTOMODE 1// =1:双向认证  =0:单向认证int main(void)
{int ret = 0;debug("-------------------- SSL Client Demo ---------------------------\r\n");#if (AUTOMODE == 1)if((ret = mbedtls_ssl_client_init(&client,mbedtls_ca_crt,mbedtls_ca_crt_len,mbedtls_client_crt,mbedtls_client_crt_len,mbedtls_client_key,mbedtls_client_key_len,"zxcvbnm.",strlen("zxcvbnm."),"ssl_client",strlen("ssl_client"),"SERVER")) != 0)
#elseif((ret = mbedtls_ssl_client_init(&client,mbedtls_ca_crt,mbedtls_ca_crt_len,NULL,0,NULL,0,NULL,0,"ssl_client",strlen("ssl_client"),"SERVER")) != 0)
#endif{debug_e(" init failed,err:%d.\r\n", ret);goto __exit;}debug(" ssl client init ok. \r\n");if((ret = mbedtls_ssl_client_connect(&client, IP, PORT)) != 0){debug_e(" connect failed,err:%X\r\n", ret);goto __exit;}debug(" ssl connect ok. \r\n");if(mbedtls_ssl_write(&client.sslctx, (const unsigned char *)"Hello Server !", strlen("Hello Server !")) < 0){debug_e(" write failed,errcode:%d.\r\n", ret);goto __exit;}debug(" %d bytes written. \r\n", strlen("Hello Server !"));do{memset(Buffer, 0X00, sizeof(Buffer));ret = mbedtls_ssl_read(&client.sslctx, Buffer, sizeof(Buffer));if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE){continue;}if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)  // 远程关闭了连接{break;}if(ret <= 0){break;}debug(" %d bytes read:[%s]\r\n", ret, Buffer);}while(1);__exit:mbedtls_ssl_client_disconnect(&client);mbedtls_ssl_client_destory(&client);return 0;
}

2、服务器代码模型

/** main.c**  Created on: 2020年10月29日*      Author: hello*/#include <stdlib.h>
#include <string.h>#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "mbedtls/config.h"#define debug_e(fmt, ...) do{fprintf(stderr, fmt, ##__VA_ARGS__);fflush(stderr);}while(0);
#define debug(fmt, ...)   do{printf(fmt, ##__VA_ARGS__);fflush(stdout);}while(0);#define IP   "192.168.31.16"
#define PORT "5004"unsigned char mbedtls_ca_crt[] =
{"-----BEGIN CERTIFICATE-----\r\n"                                      \"MIIDPTCCAiUCFAyaaimE7qW89Z0Verz2WN3cABu4MA0GCSqGSIb3DQEBCwUAMFox\r\n" \"CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoM\r\n" \"BFFEWlkxFTATBgNVBAsMDHd3dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwIBcNMjAx\r\n" \"MTA1MDgxOTM0WhgPMjEyMDEwMTIwODE5MzRaMFoxCzAJBgNVBAYTAkNOMQswCQYD\r\n" \"VQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoMBFFEWlkxFTATBgNVBAsMDHd3\r\n" \"dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\r\n" \"ggEKAoIBAQDWU0v4jZ1OPxpGJT8kGKer3tWtLE8Lc7DdDIiikerznKsBXtjxMjZH\r\n" \"+HlEjf/dp5LqQhsEfVQa7+YXJGVmdXvTpGrIkP0YiAlQscdgmFkoRcyEVJY/oCgE\r\n" \"BhIKh68otjZkVgK/E4qzpv2C6575iR4WxJG01LAVzdRvDPYyK08aXfKgTxygxJOC\r\n" \"40iQicOVZ8/s9iBfPxXXPaYf5tOf9nGi4fOba8eGa32ZtpJCBHS45Z5JYAWSM2aW\r\n" \"s9O7WQRvehw4eOza5gtw/+SlKHB4SlguwNBxz+kMS6t5PN16GPZW+vsY4aVSaXw6\r\n" \"5z2fZTTtvFoUT0j40fRF8N1BPV5ubZr5AgMBAAEwDQYJKoZIhvcNAQELBQADggEB\r\n" \"AK+6MRg6U7cT2fFsKRlhYGB1Q7pY8jn8RmdEOHwfbEFiW1as2DantVs1S8ZWgIL8\r\n" \"+gu0FlNC1QlPOVceF2SCl/44dtgXSSGqivZfnK9v8Gg7HMQMSgXtQlULu4piVpVw\r\n" \"pi3HkzIBsQiHtBaLB7ukmOmFXFXorrHbVxsIK9ZZW+OAP+E8O0byEVkyUMCLugxd\r\n" \"B8IQiGN0SmIOIuM5VoRujnLBBs8GCY+XmEf3qgHU+Tv5I6IhSL+p0eTfVP17ZFU4\r\n" \"a6xkq64n74XDOKlpIEQ9NnHpHiQmCYkMBZwC2NBNXKG/uw5PKkV51kFqaHe8T29n\r\n" \"4uhXD15/+AkOnvhSt7Uuooc=\r\n"                                         \"-----END CERTIFICATE-----\r\n"
};unsigned char mbedtls_srv_crt[] =
{"-----BEGIN CERTIFICATE-----\r\n" \"MIIDQTCCAikCFG2ck7C9+1Hyz/ipV3TxBxUYfvHbMA0GCSqGSIb3DQEBCwUAMFox\r\n" \"CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoM\r\n" \"BFFEWlkxFTATBgNVBAsMDHd3dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwIBcNMjAx\r\n" \"MTA1MDgyMDAwWhgPMjEyMDEwMTIwODIwMDBaMF4xCzAJBgNVBAYTAkNOMQswCQYD\r\n" \"VQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoMBFFEWlkxFTATBgNVBAsMDHd3\r\n" \"dy5xZHp5LmNvbTEPMA0GA1UEAwwGU0VSVkVSMIIBIjANBgkqhkiG9w0BAQEFAAOC\r\n" \"AQ8AMIIBCgKCAQEAt9su9lcpQ+UjSuk9t3WDes/XmRNvC05XfyEWELwFAJXtumAD\r\n" \"HSLD3xiZE+VPOdYkicUl9LwJmZrpS+M+777klhYUKijrinz9f3pFdT9e3s1cDFu4\r\n" \"J4+DE6rtIq7tXlS9bC54SKua+HPsVnNd3xEyxIFyEahZKAkYfB9gb9Qh/meHFQC7\r\n" \"q0erggt8/haabjvAqdXw8A1I1zgVfqTAVP9TuHAN+sZsnkA4uIXJh9bjtmQDP7k9\r\n" \"tvTO3+WJz3KwYp5Q9VeHv3zXRlnILfyyNgQuGFUyjoTnyY6DfLsYUn81Vv+e3S3H\r\n" \"NdujwhulZKY7Nc43VPunLUk9HEjGpCli8VVQpwIDAQABMA0GCSqGSIb3DQEBCwUA\r\n" \"A4IBAQB0tQ7PbyxnTWCLCbNFZMlbj2yerI5QhOI+3RKoIlkUh6OaTuJhczzhhJ5C\r\n" \"RuUqwAtxjF6AShp7yL8WQl9JHkohDi9JZ2qZMnFWigEJejjW+t66k85zh5zbYGNI\r\n" \"HV+5wJlkF+SyXZCZgAB0u2j/21itqhNSPQ/Y2UH4eENq0vNbehZiFFzdFZyqHIXl\r\n" \"N2UAT6cyWdf5WqRHmXlymSpwXgHikpnXCXYxYNvHYgRacMPMR2DqcbvkZ8FY9n8x\r\n" \"bNK0HLzmKp2Gk73MMySmsDCAnv4TXSJriR08WTAUEvVBDQQfSZGtYhXCtCS9zLAj\r\n" \"SAo+7/18VhyYyAsWq5W4fUtTY+rV\r\n"                                     \"-----END CERTIFICATE-----\r\n"
};unsigned char mbedtls_srv_key[] =
{"-----BEGIN RSA PRIVATE KEY-----\r\n" \"Proc-Type: 4,ENCRYPTED\r\n" \"DEK-Info: AES-256-CBC,D40A7C926A0DFC3E4F0B137FE4D2AC74\r\n" \"\r\n" \"xxjNIwzrrFMQ2iWhlCHh0Ck8z2tgp/C8ieXHbjUdvOzHVTLeNsGIaGK4m9mGbcBn\r\n" \"HEheWMqHAnEYTNzA2SFxZdQlzxhee1d7ATu4TSSkN4JM8Ahi3f44w2irqL3hBiHT\r\n" \"sQMRUjg62snAiNS5Cz0CllP74kZwJXFuiRWCJSFaXUI0U2yrp6AuFIOBPVSN5cvM\r\n" \"if8+8lMRaXlESB9LzQomg8q4Qh1vQGBR5k10pVn/GhngwBDm8uhCyqH0lq+RKq3H\r\n" \"wCGYmL8v1qW7CG8Wqm4UexZpgbMnOWg0xLEnr8Xvjl1YmCFWcG+wRtybEErSxlbD\r\n" \"QzWQCK51UE5HTmdD3O5F0FZ/ksopH+SD/xPpKRdMa9px8wIeAlXc5jY2U2IbaTe5\r\n" \"Bo0ma5O7QrmqxjkiVIXOT+hJgzR3xm/AxYNVB8vSP+L427C+eynI43hcHNpyVD/1\r\n" \"n60bYR9cGf6rilpW9F6fvBOAleRsQ4m40TGszwlh42HsnrLY+nNtsBr3Z7h2nCEr\r\n" \"UFfWENvqSa1+r5J9MqCnQorqvXEGSoNdtr2NPQDgSJb0cJx45XgKMqwP/i0+nz5B\r\n" \"0imaJ6/9J/oLaiNfcEJHFRsZL/Gs558oCypzfhhJEuRnrmKn4deGboGdFS+1ChiP\r\n" \"4lCIJqUEpj7ExTae/Ea7L+xd3UGmrRGnF4aJ9O4i4ElyY6CRK9O/19k2s/F5m+WP\r\n" \"LkFJMdxHDIkJWzIxix7sTVd92zBcnsoqS/h6zlU+LspfZ8GGMf4ThObi7zg80Zsk\r\n" \"xxJNahlyItZzGSeXu2FGhzt9I30gle2kIY8febB+c8OdHH+giFZGEiE6oqgbuKgc\r\n" \"8W6xqaBQpL8LnTkfizcH9IfiZdUCPwrUsUssa5PXsiehUZB0DLYNAFM7jiVZfeQM\r\n" \"GwAzPQJi2Y/GIkP7eSxRcGfB4FM2UWUBKA5awfYh7UbunGu85rgsFVfunwNXYrcd\r\n" \"BFy8CK8sXFUwhwiprawfya6iO5GXfbOeSoi3HMhbXbdcdxFxMWPBzKzag+GQhB9M\r\n" \"Q08ujKWW3WYrCvby0K5yZq4Up7+4bBQgWiifcL7laEfl0snio2oD9dtZBezgy6/n\r\n" \"vWiTW0lounaU/tK5GsHtgsgDBcOwbVLirt8KXHsWlI22weLrBLYaImgzmxXn0U7O\r\n" \"06ab+3aP12ICQY1stWLK9DowDmjCqWsBiuUoMMtB9a2yF/ra2a3QVe99N6yxGRz2\r\n" \"xmtv9NJwkTX7KSmLw0SWHHhqepwOEFW4ckkLd7Y5jD053bgSFNrBtbfPi+C9Ustv\r\n" \"GXdnvGzrAkhy9vq+tCAHuzwuBXnTMTf43fbWRbzQi7ZKVpubYFS7mqEfXXqkHhpl\r\n" \"v1P3fpURqWfSQOfPt5kIwjzc3swUKo1czZnfACcIB274FQlDOZq2sxNJYxyI2iAG\r\n" \"hK9hPqbYfswT53978BYe2R9ChDsFHFcSZyJFb4Sydr755PFFHL6LV1k2w8z4RGpJ\r\n" \"dZbH4WuYHlNs04K8TqbZGg0d8T544yHPdlMGY72YFJ4DbW/uckjSo/z4djyls6NT\r\n" \"vJPCm1ZvcTu+FyL/lEL/jNsNF17kdipDhtmhFr3KPbxKycFe+mZnhVHPTZ/Gcm3U\r\n" \"-----END RSA PRIVATE KEY-----\r\n"
};typedef struct
{mbedtls_net_context listen_netctx;mbedtls_net_context client_netctx;mbedtls_ssl_context sslctx;mbedtls_ssl_config sslcfg;mbedtls_ctr_drbg_context drbgctx;mbedtls_entropy_context etpyctx;mbedtls_x509_crt x509cacrt;mbedtls_x509_crt x509srvcrt;mbedtls_pk_context pkey;
} mbedtls_server_t;mbedtls_server_t server;size_t mbedtls_ca_crt_len = sizeof(mbedtls_ca_crt);
size_t mbedtls_srv_crt_len = sizeof(mbedtls_srv_crt);
size_t mbedtls_srv_key_len = sizeof(mbedtls_srv_key);mbedtls_x509_crt_profile x509_crt_profile =
{MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),0xFFFFFFF, /* Any PK alg    */0xFFFFFFF, /* Any curve     */2048,      /* 密钥长度为2048 */
};static int mbedtls_ssl_sig_hashes[] =
{MBEDTLS_MD_SHA512,MBEDTLS_MD_SHA384,MBEDTLS_MD_SHA256,MBEDTLS_MD_SHA224,MBEDTLS_MD_SHA1,MBEDTLS_MD_NONE
};uint8_t Buffer[1024];/*** SSL服务器网络初始化* @param  server* @param  ip     ip地址字符串形式* @param  port   端口字符串形式* @return        成功返回0,失败返回负值*/
int mbedtls_ssl_server_wait_for_connect(mbedtls_server_t* server, const void* ip, const void* port)
{int ret = 0;// 绑定本地IP地址端口if ((ret = mbedtls_net_bind(&server->listen_netctx, (const char *)ip, (const char *)port, MBEDTLS_NET_PROTO_TCP)) != 0)return -1;// 清理客户端连接mbedtls_net_free(&server->client_netctx);// 清理SSL会话信息mbedtls_ssl_session_reset(&server->sslctx);// 等待客户端连接if ((ret = mbedtls_net_accept(&server->listen_netctx, &server->client_netctx, NULL, 0, NULL)) != 0)return -2;// 设置收发数据接口函数mbedtls_ssl_set_bio(&server->sslctx, &server->client_netctx, mbedtls_net_send, mbedtls_net_recv, NULL);// 握手while ((ret = mbedtls_ssl_handshake(&server->sslctx)) != 0){if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)return -3;}// 获取验证结果if((ret = mbedtls_ssl_get_verify_result(&server->sslctx)) != 0){char vrfy_buf[128];int flags = mbedtls_ssl_get_verify_result(&server->sslctx);mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", flags );debug_e( "%s\n", vrfy_buf );
//      return -4;}return 0;
}/// 断开连接
void mbedtls_ssl_server_close(mbedtls_server_t* server)
{mbedtls_ssl_close_notify(&server->sslctx);
}/// 清理
void mbedtls_ssl_server_destory(mbedtls_server_t* server)
{mbedtls_net_free(&server->client_netctx);mbedtls_net_free(&server->listen_netctx);mbedtls_x509_crt_free(&server->x509cacrt);mbedtls_x509_crt_free(&server->x509srvcrt);mbedtls_pk_free(&server->pkey);mbedtls_ssl_free(&server->sslctx);mbedtls_ssl_config_free(&server->sslcfg);mbedtls_ctr_drbg_free(&server->drbgctx);mbedtls_entropy_free(&server->etpyctx);
}/*** SSL服务器初始化* @param  server* @param  cacrt        CA证书* @param  cacrtLength  CA证书长度* @param  srvcrt       服务器证书* @param  srvcrtLength 服务器整数长度* @param  srvkey       服务器密钥* @param  srvkeyLength 服务器密钥长度* @param  srvpwd       服务器密码* @param  srvpwdLength 服务器密码长度* @param  pers         熵字符串,任意字符串即可* @param  persLength   熵字符串长度* @return              成功返回0,失败返回负值*/
int mbedtls_ssl_server_init(mbedtls_server_t* server,const void* cacrt, size_t cacrtLength,const void* srvcrt, size_t srvcrtLength,const void* srvkey, size_t srvkeyLength,const void* srvpwd, size_t srvpwdLength,const void* pers, size_t persLength)
{int ret = 0;//// 初始化//mbedtls_net_init(&server->listen_netctx);mbedtls_net_init(&server->client_netctx);mbedtls_ssl_init(&server->sslctx);mbedtls_ssl_config_init(&server->sslcfg);mbedtls_x509_crt_init(&server->x509cacrt);mbedtls_x509_crt_init(&server->x509srvcrt);mbedtls_pk_init(&server->pkey);mbedtls_entropy_init(&server->etpyctx);mbedtls_ctr_drbg_init(&server->drbgctx);// 加载服务器证书if ((ret = mbedtls_x509_crt_parse(&server->x509srvcrt, (const unsigned char *) srvcrt, srvcrtLength)) != 0)return -1;// 加载CA证书if ((ret = mbedtls_x509_crt_parse(&server->x509cacrt, (const unsigned char *) cacrt, cacrtLength)) != 0)return -2;// 加载服务器密钥if ((ret = mbedtls_pk_parse_key(&server->pkey, (const unsigned char *) srvkey, srvkeyLength, (const unsigned char *)srvpwd, srvpwdLength)) != 0)return -3;// 设置SSL/TLS熵源if ((ret = mbedtls_ctr_drbg_seed(&server->drbgctx, mbedtls_entropy_func, &server->etpyctx, (const unsigned char *) pers, persLength)) != 0)return -4;// 设置SSL连接模式if ((ret = mbedtls_ssl_config_defaults(&server->sslcfg, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0)return -5;// 设置随机数生成器回调mbedtls_ssl_conf_rng(&server->sslcfg, mbedtls_ctr_drbg_random, &server->drbgctx);// 设置CA证书认证关联到SSL结构上mbedtls_ssl_conf_ca_chain(&server->sslcfg, &server->x509cacrt, NULL);// 设置服务器证书和密钥关联if ((ret = mbedtls_ssl_conf_own_cert(&server->sslcfg, &server->x509srvcrt, &server->pkey)) != 0)return -6;// 设置用于验证的X.509安全配置文件mbedtls_ssl_conf_cert_profile(&server->sslcfg, &x509_crt_profile);// 设置握手签名的允许/首选散列算法mbedtls_ssl_conf_sig_hashes(&server->sslcfg, mbedtls_ssl_sig_hashes);//// 设置认证模式//// MBEDTLS_SSL_VERIFY_NONE     :不检查对等证书//                              (服务器默认值,如果客户端配置为此选项那么连接是不安全的;如果服务器配置为此值那么是单向认证。)//// MBEDTLS_SSL_VERIFY_OPTIONAL :检查对等证书,但即使验证失败,握手仍将继续;//                               可以在握手完成后调用mbedtls_ssl_get_verify_result()查看验证结果。//                                (如果服务器设置为此值,那么就是双向认证)//// MBEDTLS_SSL_VERIFY_REQUIRED :同时必须出示有效证书,如果验证失败,握手将终止。//                               (客户端默认值,如果服务器设置为此值,那么就是双向认证)//mbedtls_ssl_conf_authmode(&server->sslcfg, MBEDTLS_SSL_VERIFY_REQUIRED);// 配置设置if ((ret = mbedtls_ssl_setup(&server->sslctx, &server->sslcfg)) != 0)return -7;return 0;
}int main(void)
{int ret = 0;debug("-------------------- SSL Server Demo ---------------------------\r\n");ret = mbedtls_ssl_server_init(&server,mbedtls_ca_crt,mbedtls_ca_crt_len,mbedtls_srv_crt,mbedtls_srv_crt_len,mbedtls_srv_key,mbedtls_srv_key_len,"zxcvbnm.",strlen("zxcvbnm."),"ssl_server",strlen("ssl_server"));if(ret != 0){debug_e(" ssl server init failed,errcode:%d\r\n", ret);goto __exit;}debug(" ssl server init ok. \r\n");debug(" wait for connect...\r\n");if ((ret = mbedtls_ssl_server_wait_for_connect(&server, IP, PORT)) != 0){debug_e(" wait for connect failed,errcode:%d\r\n", ret);goto __exit;}debug(" client connected.\r\n");//// 接收数据//do{ret = mbedtls_ssl_read(&server.sslctx, Buffer, sizeof(Buffer));if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE){continue;}if (ret <= 0){break;}Buffer[ret] = 0;debug(" %d bytes recv:[%s]\r\n", ret, Buffer);break;} while (1);//// 发送数据//while ((ret = mbedtls_ssl_write(&server.sslctx, (const unsigned char *)"Hello Client !", strlen("Hello Client !"))) <= 0){if (ret == MBEDTLS_ERR_NET_CONN_RESET){goto __exit;}if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE){goto __exit;}}debug(" %d bytes written.\r\n", strlen("Hello Client !"));__exit:mbedtls_ssl_server_close(&server);mbedtls_ssl_server_destory(&server);return 0;
}

ends…

EmbedTLS + Eclipse C/C++测试用例SSL客户端和服务器相关推荐

  1. Sap Byd Soap使用 SSL 客户端证书

    1.修改通讯安排为使用SSL客户端证书 2.设置客户端证书 上传证书,或者上传并下载证书 3.用SoapUI 测试系统 选择下载来的证书,或者自己创建的通讯证书,并输入密码 配置好后就可以测试系统了 ...

  2. (chap8 确认访问用户身份的认证) SSL客户端认证

    SSL客户端认证是借由HTTPS的客户端证书完成的认证方式.凭借客户端整数认证,服务器可确认访问是否来自自己登陆的客户端. 1. 步骤 step1. 接收到需要认证资源的请求,服务器会发送 Certi ...

  3. qt与JAVA服务器通信_Qt实现的SSL通信客户端和服务器

    [实例简介] Qt实现的SSL通信客户端和服务器 使用QSslSocket实现加密通信 [实例截图] [核心代码] f3a25e44-604e-4435-9e05-3f6efe57c6b0 └── s ...

  4. java使用bks双向认证_客户端与服务器SSL双向认证(客户端:Android

    客户端与服务器SSL双向认证(客户端Android-服务端vc)-含源码(一)服务端已经生成了client.p12.server.p12.ca.p12:主要实现客户端过程(二)目录结构(三)客户端注 ...

  5. eclipse 是用来写客户端的,MyEclipse 是用来写服务器端的,谐音记忆法,My 买,买服务器这样就好记了。

    总是记不住,现在只记一句话 "eclipse 是用来写客户端的,MyEclipse 是用来写服务器端的",谐音记忆法,My 买,买服务器这样就好记了.

  6. edge 错误 客户端和服务器不支持常用的 SSL 协议版本或密码套件

    不支持的协议 客户端和服务器不支持常用的 SSL 协议版本或密码套件. 解决方案: 此文章质量较低,不会获得较多流量扶持! 可能的原因为:篇幅太短,广告涉嫌违规,外链过多,缺少代码,图片涉嫌违规.此文 ...

  7. IIS SSL客户端证书(忽略/接受/必须)之三——思考验证(3)

     IIS SSL客户端证书(忽略/接受/必须)之三--思考验证(3) 2015-04-11 11:19:41 标签: blank  客户端  target  证书  style Technorati ...

  8. 谷歌浏览器提示客户端和服务器不支持一般 SSL 协议版本或加密套件(亲测有效)

    目录 一.定位问题 二.升级TLS1.2 1.原理 之前架构 调整架构 2.配置nginx 3.配置tomcat 三.访问nginx即可 最近访问一部分网站时,出现如下图所示 " 此网站无法 ...

  9. java客户端带证书访问服务端_客户端与服务器SSL双向认证(客户端:java-服务端:java)...

    客户端与服务器SSL双向认证(java-java):含源码 (一)实现技术: JSSE(Java Security Socket Extension) 是Sun为了解决在Internet上的实现安全信 ...

最新文章

  1. Myeclise下tomcat启动报错,启动超时
  2. echarts x轴文字个数太多_echarts x轴标签文字过多导致显示不全,最有效的3种解决方法...
  3. Kettle数据采集 部署安装
  4. 转: 用css把图片转为灰色图
  5. 洛谷 P1255 数楼梯 70
  6. Simulink步长
  7. oracle JOB 查询 添加 修改 删除
  8. LINQ to SQL之使用Lambda Expression批量删除数据
  9. 学生选课系统代码--分析1
  10. SqliteDeveloper使用方法及注册
  11. 应用 Remoting
  12. java integer最大值_Integer的最大值
  13. 各类顶尖经典电影500部,先收着,待有空的时候慢慢看吧!
  14. 计算机关闭自带杀毒,Win10专业版系统中关闭自带杀毒软件操作方法
  15. Vue3初识 学习记录(一)
  16. 【舰船数据集格式转换】HRSID数据集VOC转COCO
  17. 《那些年我们追过的Wrox精品红皮计算机图书》有奖活动
  18. 【2023最新】MySQL安装配置教程(5.7+8.0)
  19. 操作系统精髓与原理--复习题答案整理
  20. oracle max相同,关于oracle:具有相同名称的材料化视图和表

热门文章

  1. 回顾历史_回顾美联储历史,美国货币政策是如何演变的?
  2. 高端大气上档次的搜索引擎......
  3. 失去英国电信的华为是否会失去整个欧洲?
  4. 2022-2028全球与中国锂离子电池回收市场现状及未来发展趋势
  5. 看涨期权和看跌期权的图解
  6. java计算机毕业设计绿叶有限公司工资管理信息系统源码+系统+mysql数据库+lw文档
  7. Intellij idea 报错:Error : java 不支持发行版本5
  8. ECmall邀请注册功能构想和实现
  9. VR全景乡村,VR全景,身临其境,感受自然
  10. 商业虚拟专用网络技术十 MPLS技术