C openSSL:解密不会产生正确的纯文本
我需要在客户端和服务器之间建立两个通道,第一个是用于数据传输的UDP通道,第二个是用于发送密钥的TCP通道,第四个是用于UDP通道中的AES-128 TCP套接字在服务器上创建,如下所示: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
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?!)。扩展用于消息扩展。我认为我们需要看到更多代码和/或错误解密数据的示例,以便能够了解问题所在。