0

I have to send a randomly generated number (rng) within a packet, and, thus, have to convert a SecByteBlock. I use libcrafter to put rng array into a RawLayer packet.

I followed this answer; but it gets me an invalid conversion error.

Here's the code I use:

AutoSeededRandomPool prng;
SecByteBlock rng1;
prng.GenerateBlock( rng1, rng1.size() );

string rng1_str(reinterpret_cast<char const*>(rng1));

std::string rng1_str = std::string(rng1.data(), rng1.size());

Crafter::RawLayer number(rng1_str);

The two ideas don't work, both give me:

error: invalid conversion from ‘CryptoPP::AllocatorWithCleanup<unsigned char>::pointer {aka unsigned char*}’
to ‘const char*’ [-fpermissive]
std::string rng1_str = std::string(rng1.data(), rng1.size());

Since the RawLayer accepts as constructor a std::string or a const byte*, I'd like to convert the SecBlockByte into one of these two formats...

Community
  • 1
  • 1
3isenHeim
  • 243
  • 5
  • 22
  • Try to read the error message again, it tells you what you pass to the `std::string` constructor, and what the constructor expects. The difference between them is very small and could reasonably be solved with a simple `reinterpret_cast`. However, the bigger problem is how you will *use* the string object. Will you try to use it as text? Then you might have problems as the data is most likely *not* textual. – Some programmer dude Sep 08 '15 at 13:59
  • I think it wants a `unsigned char *`, but I tried to reinterpret the cast with that, and it didn't work either... – 3isenHeim Sep 08 '15 at 14:21
  • The error message says that you try to pass `unsigned char *`, when the constructor wants `const char *`. Try casting to `char*`. – Some programmer dude Sep 08 '15 at 14:26
  • Didn't work either. I also tried to cast to `unsigned char`... – 3isenHeim Sep 08 '15 at 14:30
  • You sure? Casting to `char*` [should work fine](http://ideone.com/V3uej5). – Some programmer dude Sep 08 '15 at 14:34
  • I know, but I got this : `error: invalid cast from type ‘CryptoPP::SecByteBlock {aka CryptoPP::SecBlock}’ to type ‘char*’ `. I think it's the `SecByteBlock`, which isn't really a unsigned char*... – 3isenHeim Sep 08 '15 at 14:44
  • 1
    Now you are doing something *different*. The error message in the question specifically says `unsigned char *`, i.e. a *pointer*. – Some programmer dude Sep 08 '15 at 14:47
  • @Eisen - Since you cited the other question and answers, I improved Eric's answer to explicitly call out the conversions for future visitors. You found it, so others will like find it, too. – jww Sep 10 '15 at 06:05
  • Now available on the Crypto++ wiki: [`SecBlock`](https://www.cryptopp.com/wiki/SecBlock). The wiki page includes conversion examples. – jww Mar 23 '18 at 19:22

2 Answers2

1

The output of the PRNG likely has an embedded NULL, so you can't operate on its data with customary C-string operations. That means the first statement is probably wrong.

string rng1_str(reinterpret_cast<char const*>(rng1));

std::string rng1_str = std::string(rng1.data(), rng1.size());

I'm not sure what you are doing with the second statement, but it needs to be cast just like the first one (and you can do away with the assignment):

std::string rng1_str(reinterpret_cast<const char*>(rng1.data()), rng1.size());

Since you said you "the RawLayer accepts as constructor a std::string or a const byte*", you might try:

SecByteBlock rng(16);
prng.GenerateBlock( rng, rng.size() );

Crafter::RawLayer number( rng.data(), rng.size() );

Also, be sure to size the SecByteBlock. A raw declaration of one is a 0-sized array with no memory block backing it. That is, rng.size() will be 0 with just the following:

SecByteBlock rng;

You can also do the following:

SecByteBlock rng;
// Make it 16-bytes in size, memory uninitialized
rng.New(16);

Or:

SecByteBlock rng;
// Make it 16-bytes in size, memory initialized to 0
rng.CleanNew(16);

If you want to get really fancy and avoid the runtime allocation of the memory block, then use a FixedSizeSecBlock:

FixedSizeSecBlock<byte, 16> rng;

But this is a more advanced technique, so don't get bogged down with it.


I find C/C++ unwillingness to automatically convert between a signed char and an unsigned char very annoying because its all just 8-bit binary data to me (I understand the need for the language rules). But I think its ridiculous I need a reinterpret_cast rather than a static_cast.

jww
  • 97,681
  • 90
  • 411
  • 885
0

As the aim was to put the SecByteBlock into a Crafter::RawLayer, I simply had to cast it into a const byte*...

The following lines do the thing.

SecByteBlock rng1;
prng.GenerateBlock( rng1, rng1.size() );

Crafter::RawLayer number(reinterpret_cast<const byte*>(rng1.data()), rng1.size());
3isenHeim
  • 243
  • 5
  • 22