1. 程式人生 > >如何實現ssl在握手階段,可以精確控制選擇何種演算法進行協商

如何實現ssl在握手階段,可以精確控制選擇何種演算法進行協商

       加密原理先暫且不詳說,這次只是把如何實現這個控制載入何種演算法思路大致說一下,大家都知道,客戶端和服務端在進行正真的應用資料通訊之前,需要建立tcp三次握手連線之後,還要進行握手協商,客戶端會把自己支援的演算法套件,產生的隨機數,還有支援的版本號,發給對端,這個階段稱為hello階段,,在這個階段,我們就可以控制選擇把何種支援的演算法套件發給伺服器,大致如下:演算法都有一個唯一的ID,這是可以區別不同的演算法,各個不同的tls/ssl版本演算法的名字可能會變化,但這個演算法ID是不會變的,就像我們人類的省份證號碼不會變,但自己的名字會變一樣。首先,我們可以定義一個數組,使用各個演算法的ID填充陣列,像下面這樣:

unsigned int g_ssl_cipher_support[32]=

{

0x03000002,

0x03000004,

0x03000005,

0x0300000A,

0x0300002F,

0x03000035,

0x0300003C,

0x0300003D,

0x03000067,

0x0300006B,

0x0300009C,

0x0300009E,

0x0300C027,

0x0300C02F,

};

由於是通過AT命令傳送,首先是在AT命令裡設定好INT32 g_ssl_cipher_flag = 0xffffffff;

g_ssl_cipher_is_support   //0不選,1選擇

g_ssl_cipher_id   //相當於陣列的下標,

再設定兩個引數:如下

    g_ssl_cipher_flag &=(~(1 << g_ssl_cipher_id));     g_ssl_cipher_flag |=(g_ssl_cipher_is_support <<g_ssl_cipher_id );

在hello階段,在這個ssl_cipher_list_to_byte()函式中,呼叫自己寫好的函式g_check_ssl_cipher_is_suppor()進行篩選我們想要的演算法,這個函式實現如下:

extern UINT32 g_ssl_cipher_flag;

BOOL g_check_ssl_cipher_is_support(SSL_CIPHER *c)

{

    UINT32 i=0;

    int g_ssl_flag=0;

    for(i=0;i<32;i++)

    {

    if(g_ssl_cipher_support[i] == c->id)      //根據ID進行選擇

    {

           g_ssl_flag=g_ssl_cipher_flag&(1 <<i);

           if(g_ssl_flag)

           {

                 return TRUE;

            }

          else

          {

                return FALSE;

          }

   }

}

return FALSE;

}

完整的ssl_cipher_list_to_bytes()函式實現如下,各個TLS或者SSL版本上都有這個函式實現:具體細節

下次找個時間不上,有時間會把SSL協議和原始碼都說一下。

int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,

                             int (*put_cb)(const SSL_CIPHER *, unsigned char *))

{

int i,j=0;

SSL_CIPHER *c;

unsigned char *q;

#ifndef OPENSSL_NO_KRB5

        int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx);

#endif /* OPENSSL_NO_KRB5 */

if (sk == NULL) return(0);

q=p;

for (i=0; i<sk_SSL_CIPHER_num(sk); i++)

{

CSW_TRACE(4,TSTXT("[ght]sk_SSL_CIPHER_num(sk)=%d\n"),sk_SSL_CIPHER_num(sk));

c=sk_SSL_CIPHER_value(sk,i);

if(c == NULL)

        continue;

if(FALSE == g_check_ssl_cipher_is_support(c))          //在這裡呼叫

{

       continue;

}

/* Skip TLS v1.2 only ciphersuites if lower than v1.2 */

if ((c->algorithm_ssl & SSL_TLSV1_2) &&

(TLS1_get_client_version(s) < TLS1_2_VERSION))

continue;

#ifndef OPENSSL_NO_KRB5

if (((c->algorithm_mkey & SSL_kKRB5) || (c->algorithm_auth & SSL_aKRB5)) &&

    nokrb5)

                    continue;

#endif /* OPENSSL_NO_KRB5 */                    

j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);

p+=j;

}

/* If p == q, no ciphers and caller indicates an error. Otherwise

 * add SCSV if not renegotiating.

 */

#if 0

if (p != q && !s->renegotiate)

{

static SSL_CIPHER scsv =

{

0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0

};

j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p);

p+=j;

#ifdef OPENSSL_RI_DEBUG

fprintf(stderr, "SCSV sent by client\n");

#endif

}

#endif

return(p-q);