openssl生成密鑰/證書


 

一、公鑰/私鑰/簽名/驗證簽名/加密/解密/非對稱加密

  對稱加密:用同一個密碼  加密/解密  文件。

  非對稱加密:加密用的一個密碼,解密用另外一組密碼。

  加密解密:公鑰加密數據,然后私鑰解密。

 

        公鑰加密的數據只有它相對應的私鑰可以解開,所以數據只有到了有私鑰的你這里,才可以解開成有用的數據。

簽名和驗證簽名:私鑰加密數據,公鑰解密。

  用私鑰對數據進行簽名,那這個數據就只有配對的公鑰可以解開,有這個私鑰的只有你,配對的公鑰解開了數據,就說明這數據是你發的,這個被稱為簽名。

 

二、加密的算法: RSA/DSA/SHA/MD5

  RSA可以用於加/解密,也可以用於簽名驗簽。

  DSA則只能用於簽名。

  SHA和MD5:摘要算法

       摘要算法:SHA和MD5:.就是通過一種算法,依據數據內容生成一種固定長度的摘要,這串摘要值與原數據存在對應關系。

       實際應用過程中,因為需要加密的數據可能會很大,進行加密費時費力,所以一般都會把原數據先進行摘要,然后對這個摘要值進行加密,將原數據的明文和加密后的摘要值一起傳給你.這樣你解開加密后的摘要值,再和你得到的數據進行的摘要值對應一下就可以知道數據有沒有被修改了。

       實際應用中,一般都是和對方交換公鑰,然后你要發給對方的數據,用他的公鑰加密,他得到后用他的私鑰解密,他要發給你的數據,用你的公鑰加密,你得到后用你的私鑰解密,這樣最大程度保證了安全性.

 

三、公鑰: CA/PEM/DER/X509/PKCS

 

四、生成證書

  1、創建私鑰:openssl genrsa -out ca/ca-key.pem 1024

       

 

  2、創建證書請求:openssl req -new -out ca-req.csr -key ca-key.pem

        

 

  3、自簽署證書:openssl x509 -req -in ca-req.csr -out ca-cert.pem -signkey ca-key.pem -days 3650

   

 

  4、將證書導出成瀏覽器支持的.p12格式 :openssl pkcs12 -export -clcerts -in ca-cert.pem -inkey ca-key.pem -out ca.p12

  

   

 1 // 服務端代碼
 2 int Test_openssl_server_v2()
 3 {
 4     OM_NetworkInit();
 5  
 6     SSL_CTX     *ctx;
 7     SSL         *ssl;
 8     X509        *client_cert;
 9  
10     char szBuffer[1024];
11     int nLen;
12  
13     struct sockaddr_in addr;
14     int len;
15     int nListenFd, nAcceptFd;
16  
17     // 初始化
18     SSLeay_add_ssl_algorithms();
19     OpenSSL_add_all_algorithms();
20     SSL_load_error_strings();
21     ERR_load_BIO_strings();
22  
23     // 我們使用SSL V3,V2
24     EXIT_IF_TRUE((ctx = SSL_CTX_new(SSLv23_method())) == NULL);
25  
26     // 要求校驗對方證書
27     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
28  
29     // 加載CA的證書
30     EXIT_IF_TRUE(!SSL_CTX_load_verify_locations(ctx, "cacert.cer", NULL));
31  
32     // 加載自己的證書
33     EXIT_IF_TRUE(SSL_CTX_use_certificate_file(ctx, "server.cer", SSL_FILETYPE_PEM) <= 0);
34  
35     // 加載自己的私鑰  
36     EXIT_IF_TRUE(SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM) <= 0);
37  
38     // 判定私鑰是否正確  
39     EXIT_IF_TRUE(!SSL_CTX_check_private_key(ctx));
40  
41     // 創建並等待連接
42     nListenFd = socket(PF_INET, SOCK_STREAM, 0);
43     struct sockaddr_in my_addr;
44     memset(&my_addr, 0, sizeof(my_addr));
45     my_addr.sin_family = PF_INET;
46     my_addr.sin_port = htons(8812);
47     my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//  INADDR_ANY;
48     if (bind(nListenFd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
49         int a = 2;
50         int b = a;
51     }
52     
53     //
54     listen(nListenFd, 10);
55  
56     memset(&addr, 0, sizeof(addr));
57     len = sizeof(addr);
58     nAcceptFd = accept(nListenFd, (struct sockaddr *)&addr, (int *)&len);
59     CPosaLog::Printf(CPosaLog::L_DEBUG, "Accept a connect from [%s:%d]\n",
60         inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
61  
62     // 將連接付給SSL  
63     EXIT_IF_TRUE((ssl = SSL_new(ctx)) == NULL);
64     SSL_set_fd(ssl, nAcceptFd);
65     int n1 = SSL_accept(ssl);
66     if (n1 == -1) {
67         const char* p1 = SSL_state_string_long(ssl);
68         int a = 2;
69         int b = a;
70     }
71     // 進行操作  
72     memset(szBuffer, 0, sizeof(szBuffer));
73     nLen = SSL_read(ssl, szBuffer, sizeof(szBuffer));
74     CPosaLog::Printf(CPosaLog::L_DEBUG, "Get Len %d %s ok\n", nLen, szBuffer);
75  
76     strcat(szBuffer, " this is from server");
77     SSL_write(ssl, szBuffer, strlen(szBuffer));
78  
79     // 釋放資源  
80     SSL_free(ssl);
81     SSL_CTX_free(ctx);
82     closesocket(nAcceptFd);
83  
84     return 0;
85 }
View Code

 

      

 

五、server證書

  1、生成server證書:openssl genrsa -out server-key.pem 1024

  

 

   2、創建證書請求:openssl req -new -out server-req.csr -key server-key.pem

 

   3、自簽署證書:openssl x509 -req -in server-req.csr -out server-cert.pem -signkey server-key.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -days 3650

         

 

  4、將證書導出成瀏覽器支持的.p12格式:openssl pkcs12 -export -clcerts -in server-cert.pem -inkey server-key.pem -out server.p12

   

   

    5、完成

    

 

六、Client證書

  生成server證書:openssl genrsa -out client-key.pem 1024 
  創建證書請求:openssl req -new -out client-req.csr -key client-key.pem
  自簽署證書:openssl x509 -req -in client-req.csr -out client-cert.pem -signkey client-key.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -days 3650
  將證書導出成瀏覽器支持的.p12格式:openssl pkcs12 -export -clcerts -in client-cert.pem -inkey client-key.pem -out client.p12

   

 

七、即:使用相同的ca生成兩個證書,一個是server.cer,一個是client.cer,注意生成server.cer的時候必須指明證書可以用於服務端的。

 

八、代碼:

// 服務端代碼
int Test_openssl_server_v2()
{
    OM_NetworkInit();
 
    SSL_CTX     *ctx;
    SSL         *ssl;
    X509        *client_cert;
 
    char szBuffer[1024];
    int nLen;
 
    struct sockaddr_in addr;
    int len;
    int nListenFd, nAcceptFd;
 
    // 初始化
    SSLeay_add_ssl_algorithms();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    ERR_load_BIO_strings();
 
    // 我們使用SSL V3,V2
    EXIT_IF_TRUE((ctx = SSL_CTX_new(SSLv23_method())) == NULL);
 
    // 要求校驗對方證書
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
 
    // 加載CA的證書
    EXIT_IF_TRUE(!SSL_CTX_load_verify_locations(ctx, "cacert.cer", NULL));
 
    // 加載自己的證書
    EXIT_IF_TRUE(SSL_CTX_use_certificate_file(ctx, "server.cer", SSL_FILETYPE_PEM) <= 0);
 
    // 加載自己的私鑰  
    EXIT_IF_TRUE(SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM) <= 0);
 
    // 判定私鑰是否正確  
    EXIT_IF_TRUE(!SSL_CTX_check_private_key(ctx));
 
    // 創建並等待連接
    nListenFd = socket(PF_INET, SOCK_STREAM, 0);
    struct sockaddr_in my_addr;
    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = PF_INET;
    my_addr.sin_port = htons(8812);
    my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//  INADDR_ANY;
    if (bind(nListenFd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
        int a = 2;
        int b = a;
    }
    
    //
    listen(nListenFd, 10);
 
    memset(&addr, 0, sizeof(addr));
    len = sizeof(addr);
    nAcceptFd = accept(nListenFd, (struct sockaddr *)&addr, (int *)&len);
    CPosaLog::Printf(CPosaLog::L_DEBUG, "Accept a connect from [%s:%d]\n",
        inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
 
    // 將連接付給SSL  
    EXIT_IF_TRUE((ssl = SSL_new(ctx)) == NULL);
    SSL_set_fd(ssl, nAcceptFd);
    int n1 = SSL_accept(ssl);
    if (n1 == -1) {
        const char* p1 = SSL_state_string_long(ssl);
        int a = 2;
        int b = a;
    }
    // 進行操作  
    memset(szBuffer, 0, sizeof(szBuffer));
    nLen = SSL_read(ssl, szBuffer, sizeof(szBuffer));
    CPosaLog::Printf(CPosaLog::L_DEBUG, "Get Len %d %s ok\n", nLen, szBuffer);
 
    strcat(szBuffer, " this is from server");
    SSL_write(ssl, szBuffer, strlen(szBuffer));
 
    // 釋放資源  
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    closesocket(nAcceptFd);
 
    return 0;
}
View Code
 1 // 客戶端代碼
 2 int Test_openssl_client_v2()
 3 {
 4     OM_NetworkInit();
 5  
 6     SSL_METHOD  *meth;
 7     SSL_CTX     *ctx;
 8     SSL         *ssl;
 9  
10     int nFd;
11     int nLen;
12     char szBuffer[1024];
13  
14     // 初始化
15     SSLeay_add_ssl_algorithms();
16     OpenSSL_add_all_algorithms();
17     SSL_load_error_strings();
18     ERR_load_BIO_strings();
19  
20     // 我們使用SSL V3,V2
21     EXIT_IF_TRUE((ctx = SSL_CTX_new(SSLv23_method())) == NULL);
22  
23     // 要求校驗對方證書
24     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
25  
26     // 加載CA的證書
27     EXIT_IF_TRUE(!SSL_CTX_load_verify_locations(ctx, "cacert.cer", NULL));
28  
29     // 加載自己的證書
30     EXIT_IF_TRUE(SSL_CTX_use_certificate_file(ctx, "client.cer", SSL_FILETYPE_PEM) <= 0);
31  
32     // 加載自己的私鑰
33     EXIT_IF_TRUE(SSL_CTX_use_PrivateKey_file(ctx, "client.key", SSL_FILETYPE_PEM) <= 0);
34  
35     // 判定私鑰是否正確
36     EXIT_IF_TRUE(!SSL_CTX_check_private_key(ctx));
37  
38     // new
39     // 創建連接
40     nFd = socket(PF_INET, SOCK_STREAM, 0);
41     struct sockaddr_in dest;
42     memset(&dest, 0, sizeof(dest));
43     dest.sin_family = AF_INET;
44     dest.sin_port = htons(8812);
45     dest.sin_addr.s_addr = inet_addr("127.0.0.1");
46     if (connect(nFd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
47         perror("Connect ");
48         exit(errno);
49     }
50  
51     // 將連接付給SSL
52     EXIT_IF_TRUE((ssl = SSL_new(ctx)) == NULL);
53     SSL_set_fd(ssl, nFd);
54     int n1 = SSL_connect(ssl);
55     if (n1 == -1) {
56         int n2 = SSL_get_error(ssl, n1);
57  
58         const char* p1 = SSL_state_string(ssl);
59     }
60  
61     // 進行操作
62     sprintf(szBuffer, "this is from client %d", getpid());
63     int nWriten = SSL_write(ssl, szBuffer, strlen(szBuffer));
64  
65     // 釋放資源
66     memset(szBuffer, 0, sizeof(szBuffer));
67     nLen = SSL_read(ssl, szBuffer, sizeof(szBuffer));
68     CPosaLog::Printf(CPosaLog::L_DEBUG, "Get Len %d %s ok\n", nLen, szBuffer);
69  
70     SSL_free(ssl);
71     SSL_CTX_free(ctx);
72     closesocket(nFd);
73  
74     return 0;
75 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM