tags:

views:

2834

answers:

8

Hi

I'm working in a C++ unmanaged project.

I need to know how can I take a string like this "some data to encrypt" and get a byte[] array which I'm gonna use as the source for Encrypt.

In C# I do

  for (int i = 0; i < text.Length; i++)
    buffer[i] = (byte)text[i];

What I need to know is how to do the same but using unmanaged C++.

Thanks!

+6  A: 

If you just need read-only access, then c_str will do it:

char const *c = myString.c_str();

If you need read/write access, then you can copy the string into a vector. vectors manage dynamic memory for you. You don't have to mess with allocation/deallocation then:

std::vector<char> bytes(myString.begin(), myString.end());
bytes.push_back('\0');
char *c = &bytes[0];
Johannes Schaub - litb
If he wants a byte array does he need the terminating '\0'? In which case you can use data() for read only.
Martin York
i wasn't sure whether he needs the \0 or not. If he doesn't he now knows that he can use .data() . thanks for commenting on that, Martin.
Johannes Schaub - litb
This answer seems correct and may work but assuming the data store for a vector of char is contiguous and won't change is dangerous.
Mark Thalman
Assuming it's contiguous is not at all dangerous, it's a guarantee of vector (first paragraph under std::vector in the C++ spec IIRC). Assuming it won't change is safe provided that certain specified functions aren't called - amounting to those which might provoke a resize().
Steve Jessop
Mark, it is very safe to "assume" that, because it's always the case that the vector is contiguous :) and it's also safe to assume the pointer is valid. you don't modify the vector so that it has to reallocate its buffer. so the vector's first element address remains the same of course.
Johannes Schaub - litb
A: 

From a std::string you can use the c_ptr() method if you want to get at the char_t buffer pointer.

It looks like you just want copy the characters of the string into a new buffer. I would simply use the std::string::copy function:

length = str.copy( buffer, str.size() );
Nick Haddad
Some implementations of std::string may use reference counting, so a copy would not necessarily result in new bytes that would be safe to write over.
Larry Gritz
A: 

If this is just plain vanilla C, then:

strcpy(buffer, text.c_str());

Assuming that buffer is allocated and large enough to hold the contents of 'text', which is the assumption in your original code.

If encrypt() takes a 'const char *' then you can use

encrypt(text.c_str())

and you do not need to copy the string.

Mark Thalman
+2  A: 

Normally, encryption functions take

encrypt(const void *ptr, size_t bufferSize);

as arguments. You can pass c_str and length directly:

encrypt(strng.c_str(), strng.length());

This way, extra space is allocated or wasted.

Arkadiy
If you are passing a pointer and a length then you should be using data() rather than c_str() to indicate it is not being used as a string.
Martin York
+3  A: 

std::string::data() would seem to be sufficient and most efficient.If you want to have non-const memory to manipulate (strange for encryption) you can copy the data to a buffer:

unsigned char buffer[mystring.length()];
memcpy(buffer, mystring.data(), mystring.length());

STL fanboys would encourage you to do:

std::copy(mystring.begin(), mystring.end(), buffer);

instead of the memcpy, but there really isn't much of an upside to this. If you need null termination use std::string::c_str() and the various string duplication techniques others have provided, but I'd generally avoid that and just query for the length. Particularly with cryptography you just know somebody is going to try to break it by shoving nulls in to it, and using std::string::data() discourages you from lazily making assumptions about the underlying bits in the string.

Christopher Smith
A: 

If you just need to read the data.

encrypt(str.data(),str.size());

If you need a read/write copy of the data put it into a vector. (Don;t dynamically allocate space that's the job of vector).

std::vector<byte>  source(str.begin(),str.end());
encrypt(&source[0],source.size());

Of course we are all assuming that byte is a char!!!

Martin York
A: 

Thanks for the answers but I think I was looking at the wrong side of the problem, let me explain this better.

I'm working in two applications, one in C# and another one in C++ unmanaged, in both applications I encrypt and decrypt data using the functions in advapi32.

The problem that I'm having is with C++. When I encrypt a string of data, sometimes I get in the output null characters ('\0') and for some reason when I try to retrieve that encrypted data and save it to another location in memory or to the disk, I cant' reach or have access to the data after the null character.

In C# I can get all the data, even the null chars and the data after them.

Obviously because of this, when I save data with C++ and try to read it again and decrypt it with C# I get bad data errors.

At the first moment I thought the problem may be something with the way in which I pass the data to the Encrypt method, and that was the reason of my first question, but now I realize the it is something with the output of the encrypt method.

I appreciate any pointers that you can give me.

Vic
std::string should not have problems with null characters inserted, but you should use size() to get the correct length.
Ismael
The problem should be in some function expecting a null terminated string, ie like strXXX functions, if this is the case use memXXX and pass size() as the correct length.
Ismael
A: 

I dont think you want to use the c# code you have there. They provide System.Text.Encoding.ASCII(also UTF-*)

string str = "some text;
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(str);

your problems stem from ignoring the encoding in c# not your c++ code

Hippiehunter