0

我正在使用 RSA 加密消息。

如果我尝试在本地加密/解密消息,一切正常,但是,当将字符串转换为void constant*以便使用这样的socket::send方法时,

int sendRes = send(socket, tempMessage.c_str(), tempMessage.size() + 1, 0);

发生以下情况,

我原来的字符串,tempMessage

“_��JE<D�p�-d�R�U���`}�+�;����|[�t�����^;D�Mn��?ÕW>...- 6���Pr��[͉dZ%�”

被截断为此,使用时tempMessage.c_str()

“_��JE<D�p�-d�R�U���`}�+�;����|[�”

我知道这是因为,在加密期间,有一个\0符号会在一次或多次之间附加,因此在使用 c_str() 时会终止那里的所有内容。

我也知道它发生在使用 send() 之前,我把它放在这里是为了让你知道我为什么首先使用 c_str()。

有没有办法绕过这个?或解决方法?

我已经看到了这个先前的答案,但对我的情况没有帮助,也找不到任何其他解决方案。

在此先感谢您的帮助!

4

2 回答 2

2

这是一个简单的例子

  • c_str()在带有 nul-chars 的字符串上显示的问题。
  • 用于发送/接收字符串的两个原语。

这个想法是在实际字符之前的固定字节数上发送/接收字符串的长度。

/**
  g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
      -pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
      -g -O0 -UNDEBUG -fsanitize=address,undefined
**/

#include <iostream>
#include <string>
#include <stdexcept>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

ssize_t
send_all(int sockfd,
         const void *buf,
         size_t len,
         int flags)
{
  const auto *p=static_cast<const char *>(buf);
  auto remaining=len;
  while(remaining)
  {
    const auto r=send(sockfd, p, remaining, flags);
    if(r<0)
    {
      return r;
    }
    remaining-=r;
    p+=r;
  }
  return len-remaining;
}

ssize_t
recv_all(int sockfd,
         void *buf,
         size_t len,
         int flags)
{
  char *p=static_cast<char *>(buf);
  auto remaining=len;
  while(remaining)
  {
    const auto r=recv(sockfd, p, remaining, flags);
    if(r<0)
    {
      return r;
    }
    if(r==0) // EOF
    {
      break;
    }
    remaining-=r;
    p+=r;
  }
  return len-remaining;
}

void
send_string(int sockfd,
            const std::string &str,
            int flags)
{
  const auto length=htonl(std::int32_t(size(str)));
  if(send_all(sockfd, &length, sizeof(length), flags)!=sizeof(length))
  {
    throw std::runtime_error{"cannot send length"};
  }
  if(send_all(sockfd, data(str), size(str), flags)!=
     static_cast<ssize_t>(size(str)))
  {
    throw std::runtime_error{"cannot send string"};
  }
}

std::string
recv_string(int sockfd,
            int flags)
{
  auto str=std::string{};
  auto length=std::int32_t{};
  const auto r=recv_all(sockfd, &length, sizeof(length), flags);
  if(r==0) // EOF
  {
    return str;
  }
  if(r!=sizeof(length))
  {
    throw std::runtime_error{"cannot receive length"};
  }
  str.resize(ntohl(length));
  if(recv_all(sockfd, data(str), size(str), flags)!=
     static_cast<ssize_t>(size(str)))
  {
    throw std::runtime_error{"cannot receive string"};
  }
  return str;
}

int
main()
{
  auto msg=std::string{};
  msg+="there is a nul-char...";
  msg+='\0';
  msg+="in the middle!";
  std::cout << "as a string <" << msg << ">\n";
  std::cout << "as a const char * <" << msg.c_str() << ">\n";
  std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
  int fd[2];
  if(socketpair(PF_LOCAL, SOCK_STREAM, 0, fd)<0)
  {
    throw std::runtime_error{"socketpair() failure"};
  }
  for(auto i=0; i<5; ++i) // very few to fit in internal buffer
  {
    send_string(fd[1], "message number "+std::to_string(i+1), 0);
  }
  close(fd[1]);
  for(;;)
  {
    const auto s=recv_string(fd[0], 0);
    if(empty(s))
    {
      break;
    }
    std::cout << '[' << s << "]\n";
  }
  close(fd[0]);
  return 0;
}
/**
as a string <there is a nul-char...in the middle!>
as a const char * <there is a nul-char...>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[message number 1]
[message number 2]
[message number 3]
[message number 4]
[message number 5]
**/
于 2021-03-15T19:52:33.917 回答
0

最后,这是一个更容易解决的问题。

由于所有消息都按照相同的类型进行加密,因此加密部分的位长度将始终相同。

就我而言,这是256,这意味着我现在可以发送-接收而没有任何进一步的问题,因为我现在知道真正的字符串长度。

如果不是这种情况,我会选择@prog-fh 答案

于 2021-03-17T18:56:37.527 回答