Weird unsigned char * concat behavior - c++

I've got two unsigned char arrays, and a char array. I want to xor both unsigned char arrays and then join a char array.
char mensaje[] = "A";
unsigned char key[] = "61181d3cfd91b0cc0890c2c0646c94f692b311ffbf93749c0aadd8ae6f04f044";
test(key, mensaje)
void test(unsigned char key[],char mensaje[]){
unsigned char pad_exterior[64];
unsigned char pad_interior[64];
for(int i =0 ; i<64; i++ ){
pad_exterior[i]= 0x5c ^ key[i];
pad_interior[i]= 0x36 ^ key[i];
}
char * result = new char[strlen(mensaje)+ 64];
copy(mensaje, mensaje + strlen(mensaje), result);
copy(pad_interior, pad_interior + 64, result + strlen(mensaje));
char * result2 = new char[strlen(mensaje)+ 64];
copy(mensaje, mensaje + strlen(mensaje), result2);
copy(pad_exterior, pad_exterior + 64, result2 + strlen(mensaje));
}
The problem is, at the end, strlen(pad_exterior) = 65 but strlen(pad_interior) =1.
However, if I replace
pad_interior[i]= 0x36 ^ key[i];
with
pad_interior[i]= 0x36;
it does work.
Why this odd behavior?
Is there a better way to accomplish what I am trying to do? I've tried over a dozen ways to copy the arrays.
Edit:
I figured I needed char arrays because I am calling EVP_DigestUpdate.
The test function basically just xor and joins the arrays.
The call is at the beginning of the code

strlen is designed to work with null terminated char arrays. It uses the \0 terminator to actually find the length.
So if 0x36 ^ key[i] is 0, your pad_interior becomes null terminated too early.
And if 0x5c ^ key[i] is never zero your pad_exterior is not null terminated. And you run into UB when you do strlen(pad_exterior). You were just a little lucky that it returned 65.

Related

strcpy_s buffer L buffer is too small && 0

i have a problem.
i tried to proceede the following steps:
char * str;
char * s="Hello";
int len = std::strlen(s);
str=new char[len +10];
strcpy_s(str,sizeof(str) ,s);
But the programm displays the error, which i write in the title.
If i replace the sizeof(str) with a number, for example 256, a pop up window appear with the message project.exe has triggered a breakpoint.
How can i solve this errors with strcpy_s??
Thank you!
The sizeof(str) returns the size of char* which is (probably) either 4 or 8 (bytes) depending on the implementation. In your case it appears to be 4 which is not enough to hold the characters that make up the "Hello" literal plus the null terminating character. Since there is not enough space the strcpy_s function invokes undefined behavior. You need at least 6 bytes which is the number of characters + 1 byte for a null character. Also instead of str=new char[len + 10]; you probably meant str = new char[len + 1]; to accommodate for the \0 character. Hence your code should be:
#include <iostream>
int main(){
char* str;
char* s = "Hello";
int len = std::strlen(s);
str = new char[len + 1];
strcpy_s(str, len + 1, s);
}
That being said prefer std::string to C-style character array.
sizeof(str) gives the size of char*, which is not the length of the allocated array. To fix this, you must give the allocated length. In this case this would be
strcpy_s(str, len + 10, s);

Convert char byte to integer value

For example , 130ABF (Hexadecimal) is equals to 1247935 (Decimal),
So my byte array is
char buf[3] = {0x13 , 0x0A , 0xBF};
and I need to retrieve the decimal value from the byte array.
Below are my sample code:
#include<iostream>
using namespace std;
int main()
{
char buf[3] = {0x13 , 0x0A , 0xBF};
int number = buf[0]*0x10000 + buf[1]*0x100 + buf[2];
cout<<number<<endl;
return 0;
}
and the result is : (Wrong)
1247679
Unless I change the
char buf[3] = {0x13 , 0x0A , 0xBF};
to
int buf[3] = {0x13 , 0x0A , 0xBF};
then It will get correct result.
Unfortunately, I must set my array as char type, anyone know how to solve this ?
Define the array as:
unsigned char buf[3];
Remember that char could be signed.
UPDATE: In order to complete the answer, it is interesting to add that "char" is a type that could be equivalent to "signed char" or "unsigned char", but it is not determined by the standard.
Array elements will be promouted to int before evaluating. So if your compiler treats char as signed you get next (assuming int is 32-bit):
int number = 19*0x10000 + 10*0x100 + (-65);
To avoid such effect you can declare your array as unsigned char arr[], or use masking plus shifts:
int number = ((buf[0] << 16) & 0xff0000)
| ((buf[1] << 8) & 0x00ff00)
| ((buf[2] << 0) & 0x0000ff;
Since your char array is signed, when you want to initialize the last element (0xBF), you are trying to assign 191 to it while the max it can store is 127: a narrowing conversion occurs... A workaround would be the following:
unsigned char[3] = { 0x13, 0x0A, 0xBF };
This will prevent the narrowing conversion. Your compiler should have given you a warning about it.

How to convert a char array to a byte array?

I'm working on my project and now I'm stuck with a problem that is, how can I convert a char array to a byte array?.
For example: I need to convert char[9] "fff2bdf1" to a byte array that is byte[4] is 0xff,0xf2,0xbd,0xf1.
Here is a little Arduino sketch illustrating one way to do this:
void setup() {
Serial.begin(9600);
char arr[] = "abcdef98";
byte out[4];
auto getNum = [](char c){ return c > '9' ? c - 'a' + 10 : c - '0'; };
byte *ptr = out;
for(char *idx = arr ; *idx ; ++idx, ++ptr ){
*ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
//Check converted byte values.
for( byte b : out )
Serial.println( b, HEX );
}
void loop() {
}
The loop will keep converting until it hits a null character. Also the code used in getNumonly deals with lower case values. If you need to parse uppercase values its an easy change. If you need to parse both then its only a little more code, I'll leave that for you if needed (let me know if you cannot work it out and need it).
This will output to the serial monitor the 4 byte values contained in out after conversion.
AB
CD
EF
98
Edit: How to use different length inputs.
The loop does not care how much data there is, as long as there are an even number of inputs (two ascii chars for each byte of output) plus a single terminating null. It simply stops converting when it hits the input strings terminating null.
So to do a longer conversion in the sketch above, you only need to change the length of the output (to accommodate the longer number). I.e:
char arr[] = "abcdef9876543210";
byte out[8];
The 4 inside the loop doesn't change. It is shifting the first number into position.
For the first two inputs ("ab") the code first converts the 'a' to the number 10, or hexidecimal A. It then shifts it left 4 bits, so it resides in the upper four bits of the byte: 0A to A0. Then the second value B is simply added to the number giving AB.
Assuming you want to parse the hex values in your string, and two letters always make up one byte value (so you use leading zeros), you can use sscanf like this:
char input[] = "fff2bdf1";
unsigned char output[4];
for (int i=0; i<4; i++) {
sscanf(&input[i*2], "%02xd", &data[i]);
}
Just shift 0 or 1 to its position in binary format :)
char lineChars[8] = {1,1,0,0,0,1,0,1};
char lineChar = 0;
for(int i=0; i<8;i++)
{
lineChar |= lineChars[i] << (7-i);
}
Example 2. But is not tested!
void abs()
{
char* charData = new char;
*charData = 'h';
BYTE* byteData = new BYTE;
*byteData = *(BYTE*)charData;
}

How to cast AnsiString to char?

What I'm troubling about is conversion. I'm using C++ Rad Studio XE8 (don't ask why cause I had to).
I have variables
AnsiString a = "D8";
char sz;
I want sz to look like this
char sz = 0xD8;
How do I cast the AnsiString a to char so that sz will end up equaling 0xD8?
I have tried memcpy, strcpy, etc. yet couldn't find solutions.
One way is:
unsigned char sz = strtol( a.c_str(), NULL, 16 );
Note that unsigned char is preferable because plain char is signed, and 0xD8 is out of range of plain char.
A more "C++Builder-ish" way of doing this is
unsigned char sz = StrToInt("0x" + a);
Though it will make an unnecessary memory allocation.
try this:
unsigned char sz = (unsigned char) std::stoul(a, 0, 16);

type cast char to Unsigned short

I'm trying to convert the characters to unsigned short but the value I'm getting in m_cmdCode is always 0. Some input would be very helpful.
int main()
{
char *temp = new char[3];
memset(temp,1,3);
unsigned short m_cmdCode = (unsigned short) atoi(temp);
printf("%d",m_cmdCode);
}
// I want m_cmdCode to be equal to 111, is it possible to do this ?
You're setting the elements of temp to the integer value 1. You want the character value '1':
memset(temp, '1', 3);
Note that you also need to NUL-terminate temp for atoi to work reliably.
it's come from your memset, you put 3 bytes with value 1 it's not the same thing than writing
strcpy(temp, "111")
maybe I reversed the src and dest