I have an encryption function declared as follows: int encrypt(unsigned char* keydata, int keydata_len, unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext). This works perfectly and now I call it according to the given snippet.
const char *password = "password";
len = encrypt(password, (int)strlen(password), (unsigned char*)(content.c_str()), (int)strlen(content.c_str()), ciphertext);
On compiling the C++ code I get an error as:
crest.cc:52:13: error: no matching function for call to 'encrypt'
len = encrypt(password, (int)strlen(password), (unsigned char*)(content.c_str()), (int)strlen(content.c_str()), ciphertext);
^~~~~~~
./aes.h:10:5: note: candidate function not viable: no known conversion from 'const char *' to 'unsigned char *' for 1st argument
int encrypt(unsigned char* keydata, int keydata_len, unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext);
What is the correct way to typecast in C++ to get around this error ?
There are several problems with this code, and the only (correct) way to fix them is to ensure that you use the correct data types in the first place.
So, instead of const char *password = "password", use unsigned char password[] = "password"; (of course, this will probably give you trouble with strlen, since it won't like unsigned char) - using sizeof(password)-1 will work in THIS instance, but is ill advised as a general solution, since password may well be not be directly available as an array - not sure quite what you should do as an "ideal" solution, really.
Now, the question can be asked whether it is actually correct to have a non-const input to the function. If you have the source for encrypt, you may want to change the function to encrypt(const unsigned char* keydata, size_t keydata_len, const unsigned char* plaintext, size_t plaintext_len, unsigned char* ciphertext) - still doesn't fix the problem with strlen of unsigned char of course, but it's what I'd expect the prototype to be for a function like this.
An alternative would be to rewrite the encrypt function to make casts to unsigned only internally, and use char * inputs (with const where relevant).
Note that it's NOT valid to cast away constness EXCEPT for cases where you know that the original content is not const (which I think is NOT guaranteed to be the case for std::string::c_str(), but std::string::data() should work)
Related
So i have this function which receives a pointer:
int myfunc( const char *token, unsigned char *plaintext )
I do my stuff and i end up with a char array:
unsigned char my_plaintext[1024];
Now i need to set that pointer (plaintext) to what's in my_plaintext.
I've tried many different ways but i haven't yet figure this one out...
This part is in a cpp file, and i've even tried:
std::string tmpstr( my_plaintext );
But this comes back with:
token_crypto.cpp:131:13: error: invalid conversion from 'char*' to 'unsigned char*' [-fpermissive]
my_plaintext
^~~~~~~~~~~~
And
std::string tmpstr( (char *)my_plaintext );
'�5�B'
this does compiles but the content is all wrong:
EDIT:
The content of my_plaintext is fine:
int myfunc( const char *token, unsigned char *plaintext ) {
unsigned char my_plaintext[1024];
... some processing stuff (specifically gcm_decrypt) to which is pass my_plaintext ...
cout << my_plaintext
// prints: hello:world
but then however i try set the contents of plaintext to whatever is in my_plaintext either fails at compilation or prints some weird characters.
If you know that plaintext already points at an array that is 1024 long (or longer) then you can use memmove():
int myfunc( const char *token, unsigned char *plaintext )
{
unsigned char my_plaintext[1024];
/* ... fill in my_plaintext here ... */
memmove(plaintext, my_plaintext, 1024);
/* ... rest of function ... */
}
Note that the parameters to memmove are destintation and then source rather than the other way round.
It's up to the caller of your function to make sure the pointer they pass in points to at least 1024 bytes.
You can use memcpy() instead in this case, but using memmove() is good practice in general.
The C++ string constructor doesn't take an unsigned char *. See the C++ reference here:
http://www.cplusplus.com/reference/string/string/string/
You need to cast the unsigned char array to a char array. See how to do that here:
How to Convert unsigned char* to std::string in C++?
I'm playing with an Arduino board and the samples provided. Trying to get a message I received to be displayed on the LCD. I'm struggling to figure out how to work with some of the pre-built code.
I get the error: invalid conversion from 'const unsigned char*' to 'const char*
I tried modify the payload parameter type but it breaks other references to MessageCallback.
Screen.print() definition in the documentation for the arduino board:
int print(unsigned int line, const char s, bool wrap)
Code:
static int MessageCallback(const unsigned char *payload)
{
int result = 200;
const char screenMsg[100];
strcpy(screenMsg,"Set Temp: ");
strcat(screenMsg,payload);
Screen.print(1, screenMsg, true);
return result;
}
Strcat's arguments are (char *, const char *). You can cast "payload" to a char* by doing "strcat(screenMsg, (char*)payload);". Read Strcat two unsigned char in C.
If you just change to char screenMsg[100]; it should work.
The print function will not change the string you provide to it, is all that
const char s
means.
I need to use methods described in RFC2617 and RFC1321, but am getting problems about converting C to C++. Mostly I have problem with a parameter is defined as unsigned char but argument is a char* variable.
I can solve errors with reinterpret_cast but thought there would be a better way, because there is lot of changes need to be done.
For example in the following line in md5c.c variable pszUserName is declared as char*, if the variable changed to unsigned char*, then strlen got errors:
IN char * pszUserName,
...
MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
Declaration of MD5Update
void MD5Update (
MD5_CTX *context, /* context */
unsigned char *input, /* input block */
unsigned int inputLen /* length of input block */
)
{
...
}
I got this error in the first place:
../Dig/digcalc.cpp: In function ‘void DigestCalcHA1(char*, char*, char*, char*, char*, char*, char*)’:
../Dig/digcalc.cpp:44:58: error: invalid conversion from ‘char*’ to ‘unsigned char*’ [-fpermissive]
MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
There is also a nice copy in Github
Technically, char, unsigned char and signed char are types incompatible with each other. The code:
MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
"should" be:
MD5Update(&Md5Ctx, (char *)pszUserName, strlen(pszUserName));
However, in my opinion, this is all rather annoying. MD5Update works equally well on char as unsigned char; we shouldn't have to make the code less readable for no real reason.
On existing codebases that use char * and unsigned char * interchangeably like this, I enable the compiler flag -Wno-pointer-sign and don't feel bad about it. It keeps the code more readable and the compiler behaves as if there were a cast.
When building my C++ application the build fails at this line of code
if (!PyTuple_GetByte(poArgs, 0, &SourceCell.window_type))
with this error
error C2664: 'PyTuple_GetByte' : cannot convert parameter 3 from
'char *' to 'unsigned char *'
This is the called function:
bool PyTuple_GetByte(PyObject* poArgs, int pos, unsigned char* ret);
The third parameter &SourceCell.window_type is type char.
Is there a way to convert/cast the parameter inside the function call like
if (!PyTuple_GetByte(poArgs, 0, reinterpret_cast<unsigned char*>(&SourceCell.window_type)))
or do I have to deal with it in another way?
From the error, the signature of the PyTuple_GetByte function was expecting a third parameter of type unsigned char*, but you passed a variable of type char* at its invocation. I think you have two options here.
You can change the signature of function PyTuple_GetByte to expect a char* parameter.
You need to convert your input variable from type char* to type unsigned char*, before you can pass it into PyTuple_GetByte.
The conversion is normally like this:
unsigned char* convert_var = reinterpret_cast<unsigned char*>(&SourceCell.window_type); // (c++ way)
or
unsigned char* convert_var = (unsigned char*)(&SourceCell.window_type); // (c way)
So, I have two types at the moment:
const unsigned char* unencrypted_data_char;
string unencrypted_data;
I'm attempting to perform a simple conversion of data from one to the other (string -> const unsigned char*)
As a result, I have the following:
strcpy((unencrypted_data_char),(unencrypted_data.c_str()));
However, I'm receiving the error:
error C2664: 'strcpy' : cannot convert parameter 1 from 'const unsigned char *' to 'char *'
Any advice? I thought using reinterpret_cast would help, but it doesn't seem to make a difference.
You can't write to a const char *, because each char pointed to is const.
strcpy writes to the first argument. Hence the error.
Don't make unencrypted_data_char const, if you plan on writing to it (and make sure you've allocated enough space for it!)
And beware of strcpy's limitations. Make sure you know how big your buffer needs to be in advance, because strcpy doesn't stop 'til it gets enough :)
well if unencrypted_data_char point to a memory that is only readable,you'd better not to write any data on it,it will certainly cause a segment fault.
e.g:
const char *a="abc";
a pointed to a readable only memory
if unencrypted_data_char is const only because you let it be(like const char* a=b),well you could use const_cast< char* >(a) to conver it.
if converting from const char* to unsigned char*.
1.you need convert from const char* to char*.use const_cast.
2.conver from char* to unsigned char*. use reinterpret_cast.