Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C openSSL:解密不会产生正确的纯文本_C_Linux_Tcp_Openssl_Encryption - Fatal编程技术网

C openSSL:解密不会产生正确的纯文本

C openSSL:解密不会产生正确的纯文本,c,linux,tcp,openssl,encryption,C,Linux,Tcp,Openssl,Encryption,我需要在客户端和服务器之间建立两个通道,第一个是用于数据传输的UDP通道,第二个是用于发送密钥的TCP通道,第四个是用于UDP通道中的AES-128 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)); soc

我需要在客户端和服务器之间建立两个通道,第一个是用于数据传输的UDP通道,第二个是用于发送密钥的TCP通道,第四个是用于UDP通道中的AES-128

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));
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
// local contains UDP port
error = bind(sock_fd, (struct sockaddr*) &local, sizeof(local));
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
      }
}
 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;
 }
UDP套接字在服务器上创建,如下所示:

listen_fd = socket (AF_INET, SOCK_STREAM, 0);
// sa_serv contains TCP port
error = bind(listen_fd, (struct sockaddr*) &sa_serv, sizeof (sa_serv));
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
// local contains UDP port
error = bind(sock_fd, (struct sockaddr*) &local, sizeof(local));
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
      }
}
 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;
 }
服务器需要能够连接到多个客户端,选择()中使用TCP和UDP套接字,如下所示:

listen_fd = socket (AF_INET, SOCK_STREAM, 0);
// sa_serv contains TCP port
error = bind(listen_fd, (struct sockaddr*) &sa_serv, sizeof (sa_serv));
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
// local contains UDP port
error = bind(sock_fd, (struct sockaddr*) &local, sizeof(local));
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
      }
}
 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;
 }
当服务器接收到UDP套接字中的数据时,服务器使用密钥对其进行解密,并使用TCP连接对接收到的IV进行解密;解密代码如下所示:

listen_fd = socket (AF_INET, SOCK_STREAM, 0);
// sa_serv contains TCP port
error = bind(listen_fd, (struct sockaddr*) &sa_serv, sizeof (sa_serv));
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
// local contains UDP port
error = bind(sock_fd, (struct sockaddr*) &local, sizeof(local));
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
      }
}
 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;
 }
int解密(无符号字符*普通,无符号字符*密钥,无符号字符*iv,无符号字符*密码,int len)
{
int i;
无符号字符buf[3000];
int outlen,tmplen;
执行副总裁;
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_密码_CTX_清理(&CTX);
返回0;
}
如果(!EVP_decryptedfinal_ex(&ctx、buf+outlen和tmplen))
{
EVP_密码_CTX_清理(&CTX);
返回0;
}
outlen+=tmplen;
EVP_密码_CTX_清理(&CTX);
printf(“\n解密长度:%d\n”,outlen);
printf(“\nBuf:”);

对于(i=0;i假设前8个字节是错误的,下面的字节是正确的,那么您使用的解密IV与用于加密的不同。解密时,IV仅影响第一个解密的块(明文的前128位)

假设末尾的字节是错误的:您是否正确地考虑了消息扩展?例如,您是否将完整的密文发送到另一端,或者您是否只传递len(明文)字节的密文

其他要点:

  • 如果您对多个UDP数据包使用相同的IV:您应该对每条消息(每个单独加密的UDP数据包)使用不同的IV
  • 您可能希望使用随机IV,并将其前置到通过UDP发送的密文中,而不是通过带外通道传递
  • TCP不是一个好的带外通道,因为它不安全

本质上,您正在做的是重新发明DTL。

您认为通过TCP套接字发送密钥/iv是一个好主意吗?您可能应该使用密钥交换协议(SCEP?!)。扩展用于消息扩展。我认为我们需要看到更多代码和/或错误解密数据的示例,以便能够了解问题所在。