c_str() is terminating my encrypted message is there a way to bypass this?

143 Views Asked by At

I am encrypting a message using RSA.

Everything works fine if I try to encrypt/decrypt the message locally, however, when converting the string to void constant* in order to use the socket::send method like so,

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

the following happens,

My original string, tempMessage

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

is truncated to this, when using tempMessage.c_str()

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

I do know this is because, during encryption, there is a \0 symbol that gets appended in between once or several times, terminating thus everything there when using c_str().

I also know it happens before using send(), I put it here so that you know why I am using c_str() in the first place.

It's there a way to bypass this? or a workaround?

I have seen this previous answer but did not help with my situation and could not find any other solution out there.

Thanks in advance for the help!

2

There are 2 best solutions below

0
Edgar Hernandez On BEST ANSWER

In the end, it was an easier fix.

Since all messages are encrypted following the same type, the length of the bits will always be the same for the encrypted part.

In my case, this was 256, meaning that I can now send-receive without any further issues since I now know the real string length.

If this would not have been the case, I would have gone with @prog-fh answer

0
prog-fh On

Here is a simple example showing

  • the problem with displaying c_str() on a string with nul-chars.
  • two primitives for sending/receiving strings.

The idea is to send/receive the length of the string on a fixed number of bytes before the actual 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]
**/