2012-04-20 11 views
1

クライアントとサーバーの間に2つのチャネルを確立する必要があります。最初はデータ送信用のUDPチャネルで、もう1つは鍵を送信するためのTCPチャネル、UDPチャネルのAES-128ではivです。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)); 

Serverは、複数のクライアントに接続できるようにする必要があり、 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を使用してそれを復号化します。クライアントから受信した暗号鍵と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; 
} 

が、結果プレーンテキストが正しい(8周りのバイトが間違っている)であることが判明していない次のように復号化コードがあります。さて、暗号が間違っているかもしれないと主張するかもしれないし、鍵やivが問題を抱えているかもしれません。私はそれらのすべてを検証した。

しかし、私のサーバーが1台のクライアントにしか接続されていないと思うと、復号化コードが正しく解読されるという奇妙な状況があります。 select()でTCPソケットを使用せずにselect()を使用して接続を受け入れるとき&キー/ ivをただ1つのクライアントから取得する(接続を受け取り、クライアントからキー/ ivを受け取るコードは正確ですselect()内で使用した場合と同じ)、select()でUDPソケットを使用してデータを送受信します。受信した暗号化データが正しく解読されます。

私が理解できないことは、select()fd_setにTCPソケットを置くことによって、なぜ同じ暗号化コードが問題を作り出しているのか、ということです。正しい暗号、鍵、IVを得ることができます。

誰でも説明がありますか?

ありがとうございました。

+0

TCPソケットでkey/ivを送信することをお勧めしますか?鍵交換プロトコル(SCEP ?!)を使用する必要があります。 –

答えて

0

最初の8バイトが間違っていて、次のバイトが正しいと仮定すると、暗号化に使用したものとは異なるIVを暗号化に使用しています。解読するとき、IVは最初に解読されたブロック(平文の最初の128ビット)にのみ影響します。

最後のバイトが間違っていると仮定します。メッセージ拡張を正しく考慮していますか?私。あなたは完全な暗号文をもう片方に送るのですか、または暗号文のlen(平文)バイトだけを渡していますか?

見所:あなたは、複数のUDPパケットに対して同じIVを再利用している場合は

  • :あなたは、各メッセージ(それぞれ個別に暗号化されたUDPパケット)に異なるIVを使用する必要があります。
  • ランダムIVを使用して、帯域外チャネル経由で送信する代わりに、UDP経由で送信する暗号文の前に付加することができます。
  • TCPは安全ではないため、帯域外のチャネルではありません。

本質的に、あなたがやっていることは、DTLSを改革することです。

+0

間違った8バイトが散在しています。使用されるIVは正しい。 – Jake

+0

メッセージの拡張のために拡張されました。私は、問題が何であるかを見るために、より多くのコードや誤って復号化されたデータの例を見る必要があると思います。 –

関連する問題