2012-04-20 48 views
1

我需要在客戶端和服務器之間建立兩個通道,第一個是用於數據傳輸的UDP通道,第二個是用於發送密鑰的TCP通道,UDP通道用於AES-128。openSSL:解密不會導致正確的純文本

TCP套接字在服務器創建如下:

listen_fd = socket (AF_INET, SOCK_STREAM, 0); 
// sa_serv contains TCP port 
error = bind(listen_fd, (struct sockaddr*) &sa_serv, sizeof (sa_serv)); 

UDP套接字在服務器創建如下:

sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 
// local contains UDP port 
error = bind(sock_fd, (struct sockaddr*) &local, sizeof(local)); 

服務器需要能夠連接到多個客戶端, TCP和UDP套接字在select()的使用如下:

max = (listen_fd > sock_fd) : listen_fd : sock_fd; 
fd_set set; 
FD_ZERO(&set); 
FD_SET(listen_fd, &set); FD_SET(sock_fd, &set); 

while(1) 
{ 
     select(max + 1, &set, NULL, NULL, NULL); 

     if(FD_ISSET(listen_fd, &set){ 
      // server accepts connection 
      // server receives key and IV over TCP connection 
     } 
     if(FD_ISSET(sock_fd, &set){ 
      // server receives encrypted data from client using UDP socket 
     } 
} 

當服務器接收數據I n UDP套接字,服務器使用使用TCP連接接收的密鑰和IV解密它;解密代碼如下:

int decrypt(unsigned char *plain, unsigned char *key, unsigned char *iv, unsigned char *cipher, int len) 
{ 
    int i; 

    unsigned char buf[3000]; 
    int outlen, tmplen; 
    EVP_CIPHER_CTX ctx; 
    EVP_CIPHER_CTX_init(&ctx); 
    EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv); 

    if(!EVP_DecryptUpdate(&ctx, buf, &outlen, cipher, len)) 
    { 
      EVP_CIPHER_CTX_cleanup(&ctx); 
      return 0; 
    } 

    if(!EVP_DecryptFinal_ex(&ctx, buf + outlen, &tmplen)) 
    { 
      EVP_CIPHER_CTX_cleanup(&ctx); 
      return 0; 
    } 

    outlen += tmplen; 
    EVP_CIPHER_CTX_cleanup(&ctx); 

    printf("\nLength decrypted :%d\n",outlen); 

    printf("\nBuf: "); 
    for(i=0; i<outlen; i++){ 
      plain[i] = outbuf[i];  
     printf(" %02x ",buf[i]); 
    } 
    printf("\n"); 

    return outlen; 
} 

當從客戶端接收的密碼傳遞給該函數隨着密鑰和IV,結果純文本不變成是正確的(大約8個字節是錯誤的)。現在,人們可能會認爲密碼可能是錯的,或者密鑰或iv可能有問題;我驗證了所有這些。

但奇怪的情況存在,當我認爲我的服務器只連接到一個客戶端時,上面的解密代碼正確解密;當我不在select()中使用我的TCP套接字並在外部使用它時(select)()接受連接&只從一個客戶端獲得key/iv(用於接受連接並從客戶端接收key/iv的代碼就是與在select()中使用時相同,而在select()中只使用UDP套接字來發送/接收數據;收到的加密數據被正確解密。

我無法理解的是,通過將TCP套接字放在select()fd_set中,爲什麼相同的解密代碼會產生問題,儘管我得到了正確的密碼,密鑰和IV。

有沒有人對此有過解釋?

謝謝。

+0

你認爲通過TCP套接字發送key/iv是個好主意嗎?你可能應該使用密鑰交換協議(SCEP ?!)。 – 2012-04-20 06:58:25

回答

0

假設正好前8個字節是錯誤的,並且後面的字節是正確的,那麼您使用的是不同於IV的加密解密。解密時,IV僅影響第一個解密塊(第一個128位明文)。

假設最後的字節是錯誤的:您是否正確地將消息擴展考慮在內?即你是否將完整的密文發送到另一端,還是隻傳遞len(明文)字節的密文?

附加點:

  • 如果你是用於多個UDP數據包相同的IV重新使用:你應該使用對每條消息不同IV(每個分別加密UDP數據包)。
  • 您可能想要使用隨機IV並將其前置到您通過UDP發送的密文,而不是通過帶外信道傳遞它。
  • TCP不是一個好的帶外通道,因爲它不安全。

基本上,你正在做的是重塑DTLS。

+0

錯誤的8個字節是分散的。使用的IV是正確的。 – Jake 2012-04-20 11:39:11

+0

擴展信息擴展。我想我們需要看到更多的代碼和/或錯誤解密數據的例子,以便能夠看到問題所在。 – 2012-04-20 11:46:38