std::string to BYTE[] - c++

My goal is to get this:
BYTE Data1[] = {0x6b,0x65,0x79};
BYTE Data2[] = {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
But my starting point is:
std::string msg = "message";
std::string key = "key";
I am not able to get from std::string to BYTE[].
I tried the following:
std::vector<BYTE> msgbytebuffer(msg.begin(), msg.end());
BYTE* Data1 = &msgbytebuffer[0];
This didn't cause compile or run time error. However, the end result (I feed this to a winapi function - crypto api) was not the same as when I used the actual byte array like in top most ({0x6D,0x65,0x73,0x73,0x61,0x67,0x65}).

You can use string::c_str() function which returns a pointer to c style string that can be passed to winapi functions like:
foo(string.c_str());
What it actually does is that it returns a pointer to an array that contains a null-terminated sequence of characters.
I suppose BYTE[] is actually a char array. You can assign your std::string to char array by doing:
std::string str = "hello";
BYTE byte[6]; // null terminated string;
strcpy(byte, str.c_str()); // copy from str to byte[]
If you want to copy the str without the 0 at the end, use strncpy instead:
BYTE byte[5];
strncpy(byte, str.c_str(), str.length());

Seems me that winapi is waiting a null terminated c-string. You can achieve that by using:
msg.c_str();
or, using your BYTE type, something like that:
std::vector<BYTE> msgbytebuffer(msg.length() + 1, 0);
std::copy(msg.begin(), msg.end(), msgbytebuffer.begin());

Related

Salsa20 using Crypto++

I am trying to use the salsa20 code in the crypto++ Library. ( http://www.cryptopp.com/) to communicate between two programs.
Both programs use the same code which follows
std::string salsaDo(std::string key, std::string msg, byte iv[STREAM_IV_LENGTH]) {
//Set up byte arrays for proccess
byte *plaintextBytes = (byte *)msg.c_str();
byte *ciphertextBytes = new byte[msg.length()];
byte *reversetextBytes = new byte[msg.length()];
//Set up key array
byte* keyBytes = (byte *)key.substr(0, STREAM_KEY_LENGTH).c_str();
//Peform encryption method
Salsa20::Encryption salsa;
salsa.SetKeyWithIV(keyBytes, STREAM_KEY_LENGTH, iv);
salsa.ProcessData(ciphertextBytes, plaintextBytes, msg.length());
salsa.SetKeyWithIV(keyBytes, STREAM_KEY_LENGTH, iv);
salsa.ProcessData(reversetextBytes, ciphertextBytes, msg.length());
std::string ivStr((char*)iv, STREAM_IV_LENGTH);
std::cout << "____\nK:" << key.c_str();
std::cout << "\nI:" << ivStr.c_str();
std::cout << "\nM:" << msg.c_str();
std::cout << "\nE:" << std::string((const char *)ciphertextBytes, msg.length()).c_str();
std::cout << "\nR:" << std::string((const char *)reversetextBytes, msg.length()).c_str();
std::cout << "\n____\n";
//return msg;
//return string
return std::string((const char *)ciphertextBytes, msg.length());
}
An image from the programs is at http://s21.postimg.org/wgfmkjcn9/encrypt.png
Explanation:
Step1 : plain text is encrypted (server-M to server-E)
Step2 : encrypted text is decrypted (Server-E to server-R and client-M to client-E.) These two should give the same result but don't
Step3 : client-E is run through again to check that it equals the msg the server sent.
There are a few problems with this code.
This line technically invokes Undefined Behavior:
byte* keyBytes = (byte *)key.substr(0, STREAM_KEY_LENGTH).c_str();
In this case, the substr() call returns a temporary std::string object containing the substring. The lifetime of this temporary std::string extends through the evaluation of the entire line (the full expression). The lifetime of the C string returned by std::string::c_str() is the same as the std::string, except that it is invalidated by a mutating operation. Thus, in this full expression, keyBytes is likely an invalid pointer once the line has executed.
You can fix the problem by overwriting key to the desired substring. In this case, assigning to key ensures that the lifetime is extended through where it is used:
key = key.substr(0, STREAM_KEY_LENGTH);
const byte* keyBytes = static_cast<const byte*>(key.c_str());
This salsaDo() function leaks memory. The byte arrays created by:
byte *ciphertextBytes = new byte[msg.length()];
byte *reversetextBytes = new byte[msg.length()];
.. are not freed. Consider using a std::unique_ptr<byte[]>:
std::unique_ptr<byte[]> ciphertextBytes(new byte[msg.length()]);
std::unique_ptr<byte[]> reversetextBytes(new byte[msg.length()]);
C++ does not technically support passing arrays to functions. The parameter byte iv[STREAM_IV_LENGTH] is actually treated as if you had written byte* iv instead.
You could pass a reference to the array. Also, for const-correctness, you should mark the initialization vector bytes const:
std::string salsaDo(std::string key, std::string msg, const byte (&iv)[STREAM_IV_LENGTH])
{
//...
}
I wouldn't use a std::string to store the key, or really any array of bytes such as the returned encrypted bytes. Consider using a std::unique_ptr<byte[]> or std::shared_ptr<byte[]>, or passing a reference to a const array, or passing a pointer and length (e.g. const byte* key and size_t keyLength).

C++ String to byteArray Convertion and Addition

I have a string which I want to convert to a byteArray, and then I want this byteArray to be added to another byteArray, but at the beginning of that byteArray.
Let us say this is the string I have
string suffix = "$PMARVD";
And this is the existing byteArray that I have (ignore the object there, it is a .proto object which is irrelevant now):
int size = visionDataMsg.ByteSize(); // see how big is it
char* byteArray = new char[size]; //create a bytearray of that size
visionDataMsg.SerializeToArray(byteArray, size); // serialize it
So what I want to do is something like this:
char* byteArrayforSuffix = suffix.convertToByteArray();
char* byteArrayforBoth = byteArrayforSuffix + byteArray;
Anyway of doing this in C++?
Edit: I should add that after the concatenation operation, the complete byteArrayforBoth is to be processed in:
// convert bytearray to vector
vector<unsigned char> byteVector(byteArrayforBoth, byteArrayforBoth + size);
the whole idea behind std::string is to wrap the C style strings (null terminated charcaters/bytes array) with a class that manages everything.
you can excess the inner characters array with std::string::data method. example :
std::string hello ("hello") , world(" world");
auto helloWorld = hello + world;
const char* byteArray = helloWorld.data();
EDIT:
ByteArray is a built-in type of char[] or unsigned char[], unlike Java or C#, you can't just "append" built-in byte array to another. as you suggested, you simply want a vector of unsigned characters. in this situation I would simply create a utility-function that utilizes push_back:
void appendBytes(vector<unsigend char>& dest,const char* characterArray,size_t size){
dest.reserve(dest.size() + size);
for (size_t i=0;i<size;i++){
dest.push_back(characterArray[i]);
}
}
now , with the objects you provided:
std::vector<unsigned char> dest;
appendBytes(dest, suffix.data(),suffix.size());
auto another = visionDataMsg.SerializeToArray(byteArray, size);
appendBytes(dest,another,size);
Scrap built-in arrays. You have vectors. Here is the fully working, type-safe solution which took me 3 minutes to type:
int size = visionDataMsg.ByteSize(); // see how big is it
std::vector<char> byteArray(size);
visionDataMsg.SerializeToArray(&byteArray[0], size); // serialize it
std::string str("My String");
byteArray.reserve(byteArray.size() + str.size());
std::copy(str.begin(), str.end(), std::back_inserter(byteArray));

memcpy CString to char*

I'm trying to copy a CString to a char* using memcpy() and I have difficulties doing it. In fact, only the first character is copied. Here is my code:
CString str = _T("something");
char* buff = new char();
memcpy(buff, str, str.GetLength() + 1);
After this, all that buff contains is the letter s.
You probably are mixing ASCII and Unicode strings. If compiling with Unicode setting, then CString stores a Unicode string (two bytes per character, in your case each second byte is 0 and thus looks like an ASCII string terminator).
If you want all ASCII:
CStringA str = "something";
char* buff = new char[str.GetLength()+1];
memcpy(buff, (LPCSTR)str, str.GetLength() + 1);
If you want all Unicode:
CStringW str = L"something";
wchar_t* buff = new wchar_t[str.GetLength()+1];
memcpy(buff, (LPCWSTR)str, sizeof(wchar_t)*(str.GetLength() + 1));
If you want it working on both settings:
CString str = _T("something");
TCHAR* buff = new TCHAR[str.GetLength()+1];
memcpy(buff, (LPCTSTR)str, sizeof(TCHAR) * (str.GetLength() + 1));
If you want to convert a Unicode string to an ASCII string:
CString str = _T("something");
char* buff = new char[str.GetLength()+1];
memcpy(buff, (LPCSTR)CT2A(str), str.GetLength() + 1);
Please also recognize the casts from str to LPCSTR, LPCWSTR or LPCTSTR and the corrected buffer allocation (need multiple characters and not only one).
Also, I am not quite sure if this is really what you need. A strdup for example looks much simpler than a new + memcpy.
You have only allocated memory to hold a char variable. To do what you intend, you need to allocate enough memory to hold the complete string.
CString str = _T("something");
LPTSTR buff = new TCHAR[(str.GetLength()+1) * sizeof(TCHAR)]; //allocate sufficient memory
memcpy(buff, str, str.GetLength() + 1);
You are
Only allocating one char, which won't be enough unless the CString is empty, and
copying the CString instance instead of the string it represents.
Try
CString str = _T("something");
int size = str.GetLength() + 1;
char* buff = new char[size];
memcpy(buff, str.GetBuffer(), size);

Why is the following C++ code printing only the first character?

I am trying to convert a char string to a wchar string.
In more detail: I am trying to convert a char[] to a wchar[] first and then append " 1" to that string and the print it.
char src[256] = "c:\\user";
wchar_t temp_src[256];
mbtowc(temp_src, src, 256);
wchar_t path[256];
StringCbPrintf(path, 256, _T("%s 1"), temp_src);
wcout << path;
But it prints just c
Is this the right way to convert from char to wchar? I have come to know of another way since. But I'd like to know why the above code works the way it does?
mbtowc converts only a single character. Did you mean to use mbstowcs?
Typically you call this function twice; the first to obtain the required buffer size, and the second to actually convert it:
#include <cstdlib> // for mbstowcs
const char* mbs = "c:\\user";
size_t requiredSize = ::mbstowcs(NULL, mbs, 0);
wchar_t* wcs = new wchar_t[requiredSize + 1];
if(::mbstowcs(wcs, mbs, requiredSize + 1) != (size_t)(-1))
{
// Do what's needed with the wcs string
}
delete[] wcs;
If you rather use mbstowcs_s (because of deprecation warnings), then do this:
#include <cstdlib> // also for mbstowcs_s
const char* mbs = "c:\\user";
size_t requiredSize = 0;
::mbstowcs_s(&requiredSize, NULL, 0, mbs, 0);
wchar_t* wcs = new wchar_t[requiredSize + 1];
::mbstowcs_s(&requiredSize, wcs, requiredSize + 1, mbs, requiredSize);
if(requiredSize != 0)
{
// Do what's needed with the wcs string
}
delete[] wcs;
Make sure you take care of locale issues via setlocale() or using the versions of mbstowcs() (such as mbstowcs_l() or mbstowcs_s_l()) that takes a locale argument.
why are you using C code, and why not write it in a more portable way, for example what I would do here is use the STL!
std::string src = std::string("C:\\user") +
std::string(" 1");
std::wstring dne = std::wstring(src.begin(), src.end());
wcout << dne;
it's so simple it's easy :D
L"Hello World"
the prefix L in front of the string makes it a wide char string.

Combining std::string and std::vector<char>

This is not the actual code, but this represents my problem.
std::string str1 = "head";
char *buffer = "body\0body"; // Original code has nullbytes;
std::string str2 = "foot";
std::vector<char> mainStr(buffer, buffer + strlen(buffer));
I want to put str1 and str2 to mainStr in an order:
headbody\0bodyfoot
So the binary data is maintained. Is this possible to do this?
PS: Thanks for telling the strlen part is wrong. I just used it to represent buffer's length. :)
There should be some way of defining length of data in "buffer".
Usually character 0 is used for this and most of standard text functions assume this. So if you use character 0 for other purposes, you have to provide another way to find out length of data.
Just for example:
char buffer[]="body\0body";
std::vector<char> mainStr(buffer,buffer+sizeof(buffer)/sizeof(buffer[0]));
Here we use array because it provides more information that a pointer - size of stored data.
You cannot use strlen as it uses '\0' to determine the end of string. However, the following will do what you are looking for:
std::string head = "header";
std::string foot = "footer";
const char body[] = "body\0body";
std::vector<char> v;
v.assign(head.begin(), head.end());
std::copy(body, body + sizeof(body)/sizeof(body[0]) - 1, std::back_inserter<std::vector<char> >(v));
std::copy(foot.begin(), foot.end(), std::back_inserter<std::vector<char> >(v));
Because the character buffer adds an NUL character at the end of the string, you'll want to ignore it (hence the -1 from the last iterator).
btw. strlen will not work if there are nul bytes in your string!
The code to insert into the vector is:
front:
mainStr.insert(mainStr.begin(), str1.begin(), str1.end());
back:
mainStr.insert(mainStr.end(), str2.begin(), str2.end());
With your code above (using strlen will print)
headbodyfoot
EDIT: just changed the copy to insert as copy requires the space to be available I think.
You could use std::vector<char>::insert to append the data you need into mainStr.
Something like this:
std::string str1 = "head";
char buffer[] = "body\0body"; // Original code has nullbytes;
std::string str2 = "foot";
std::vector<char> mainStr(str1.begin(), str1.end());
mainStr.insert(mainStr.end(), buffer, buffer + sizeof(buffer)/sizeof(buffer[0]));
mainStr.insert(mainStr.end(), str2.begin(), str2.end());
Disclaimer: I didn't compile it.
You can use IO streams.
std::string str1 = "head";
const char *buffer = "body\0body"; // Original code has nullbytes;
std::string str2 = "foot";
std::stringstream ss;
ss.write(str1.c_str(), str1.length())
.write(buffer, 9) // insert real length here
.write(str2.c_str(), str2.length());
std::string result = ss.str();
std::vector<char> vec(result.c_str(), result.c_str() + result.length());
str1 and str2 are string objects that write the text.
I wish compilers would fail on statements like the declaration of buffer and I don't care how much legacy code it breaks. If you're still building it you can still fix it and put in a const.
You would need to change your declaration of vector because strlen will stop at the first null character. If you did
char buffer[] = "body\0body";
then sizeof(buffer) would actually give you close to what you want although you'll get the end null-terminator too.
Once your vector mainStr is then set up correctly you could do:
std::string strConcat;
strConcat.reserve( str1.size() + str2.size() + mainStr.size() );
strConcat.assign(str1);
strConcat.append(mainStr.begin(), mainStr.end());
strConcat.append(str2);
if vector was set up using buffer, buffer+sizeof(buffer)-1
mainStr.resize(str1.length() + str2.length() + strlen(buffer));
memcpy(&mainStr[0], &str1[0], str1.length());
memcpy(&mainStr[str1.length()], buffer, strlen(buffer));
memcpy(&mainStr[str1.length()+strlen(buffer)], &str2[0], str2.length());