如何實現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);