我需要在客戶端和服務器之間建立兩個通道,第一個是用於數據傳輸的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。
有沒有人對此有過解釋?
謝謝。
你認爲通過TCP套接字發送key/iv是個好主意嗎?你可能應該使用密鑰交換協議(SCEP ?!)。 – 2012-04-20 06:58:25