2012-04-20 2 views
1

클라이언트와 서버 사이에 두 개의 채널을 설정해야합니다. 첫 번째는 데이터 전송을위한 UDP 채널이고 두 번째는 키를 전송하는 TCP 채널이며, iv는 UDP 채널의 AES-128입니다. 다음과 같이openSSL : 암호 해독이 올바른 일반 텍스트가 아닙니다.

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 소켓이 서버에 생성되어 다음과 같이

TCP 소켓은 서버에서 생성됩니다

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 
     } 
} 

서버가 데이터를 수신하면 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가 문제가 될 수도 있다고 주장 할 수도 있습니다. 나는 그들 모두를 확인했다.

그러나 서버가 하나의 클라이언트에만 연결될 때 위의 암호 해독 코드가 올바르게 해독되는 이상한 상황이 있습니다. select()에서 TCP 소켓을 사용하지 않고 select()를 사용하여 연결을 수락하면 & 하나의 클라이언트에서 키/iv를 가져옵니다 (연결을 수락하고 클라이언트에서 키/iv를 수신하는 코드는 정확히 select() 내부에서 사용될 때와 같은), select()에서 UDP 소켓을 사용하여 데이터를 보내고 받는다. 수신 된 암호화 된 데이터가 올바르게 해독됩니다.

내가 이해할 수없는 것은 select() fd_set에 TCP 소켓을 넣음으로써 왜 똑같은 암호 해독 코드가 문제가되는지, 올바른 암호, 키 및 IV를 얻는다는 사실에 고무되어 있습니다.

누구에게도 설명이 있습니까?

감사합니다.

+0

TCP 소켓을 통해 key/iv를 보내는 것이 좋습니다. 키 교환 프로토콜 (SCEP ?!)을 사용해야 할 수도 있습니다. –

답변

0

정확하게 처음 8 바이트가 잘못되어 다음 바이트가 올바른 것으로 가정하면 암호화에 사용했던 것보다 다른 IV를 사용합니다. 해독 할 때 IV는 해독 된 첫 번째 블록 (일반 텍스트의 처음 128 비트)에만 영향을 미칩니다.

마지막 바이트가 잘못되었다고 가정합니다. 메시지 확장을 올바르게 고려하고 있습니까? 나는. 다른 쪽 끝으로 전체 암호문을 보내고 있습니까? 아니면 len (plaintext) 바이트 만 암호문을 전달하고 있습니까?

추가 점수 경우

  • 있니 다시 사용하여 여러 UDP 패킷을 동일한 IV : 각 메시지 다른 IV (각각 별도로 암호화 된 UDP 패킷)을 사용한다.
  • 임의의 IV를 사용하여 대역 외 채널을 통해 전달하는 대신 UDP를 통해 보내는 암호문 앞에 임의의 IV를 추가 할 수 있습니다.
  • TCP는 안전하지 않으므로 대역 외 채널이 적합하지 않습니다.

본질적으로 당신이하는 일은 DTLS를 재발 명하는 것입니다.

+0

잘못된 8 바이트가 흩어져 있습니다. 사용 된 IV가 정확합니다. – Jake

+0

메시지 확장 용으로 확장되었습니다. 나는 문제가 무엇인지를 알 수 있도록 더 많은 코드와/또는 잘못 해독 된 데이터의 예를 볼 필요가 있다고 생각한다. –

관련 문제