C++ zLib Byte array Compressing - c++

After getting my first problem solved at C++ zLib compress byte array i faced another problem
void CGGCBotDlg::OnBnClickedButtonCompress()
{
// TODO: Add your control notification handler code here
z_const char hello[256];
hello[0] = 0x0A;
hello[1] = 0x0A;
hello[2] = 0x0A;
hello[3] = 0x0A;
hello[4] = 0x0A;
hello[5] = PKT_END;
hello[6] = PKT_END;
hello[7] = PKT_END;
Byte compr[256];
uLong comprLen = sizeof(compr);
int ReturnCode;
ReturnCode = Compress(compr, comprLen, hello, Z_DEFAULT_COMPRESSION);
g_CS.Send(&compr,comprLen);
}
int CGGCBotDlg::Compress(Byte Compressed[], uLong CompressedLength, CHAR YourByte[], int CompressionLevel)
{
int zReturnCode;
int Len;
for (int i = 0 ; i <= 10240 ; i++)
{
if (YourByte[i] == PKT_END && YourByte[i+1] == PKT_END && YourByte[i+2] == PKT_END)
{
Len = i - 1;
break;
}
}
uLong Length = (uLong)(sizeof(YourByte) * 1.0001) + 12;
zReturnCode = compress2(Compressed, &Length, (const Bytef*)YourByte, Len,CompressionLevel);
return zReturnCode;
}
Im trying to compress hello[] wich is actually 5 bytes (I want to compress first 5 bytes)
The expected result after compressing is : 0x78,0x9C,0xE3,0xE2,0x02,0x02,0x06,0x00,0x00,0xCE,0x00,0x33
But what I get after compressing is just the first 4 bytes of expected result and another bytes are just something else.
And my second problem is that i want to replcae 256 in Byte compr[256] with the exact number of bytes after decompressing original buffer (which is 12 in my case)
Would be great if someone correct me
Thanks

this line is wrong:
Len = i - 1;
because when i is 5, you do Len = i - 1; so len will be 4, but you want compress 5 bytes. just use:
Len = i;
another problem comprLen is never been assigned a value. In Compress(Byte Compressed[], uLong CompressedLength..), itCompressedLength is not used. I assume you want its value back. you should define like this:
Compress(Byte Compressed[], uLong& CompressedLength..)
and change the line to use CompressedLength instead of using length:
zReturnCode = compress2(Compressed, &CompressedLength, (const Bytef*)YourByte, Len,CompressionLevel);

Related

Dump Lora.read() to array

I want to dump chars from a Lora transmitter using Arduino Nano. With this line I assume it can be store the chars into an array:
char* dump = (char)LoRa.read();
char in[255];
strcpy(in, dump);
char str[] = in;
But unfortunately I get this compiler error:
exit status 1
initializer fails to determine size of 'str'
How I fix it?
UPDATE
I give my entire code. I used shox96 shox96 from siara-cc for my objective to compress the data from Lora.read().
void print_compressed(char *in, int len) {
int l;
byte bit;
//Serial.write("\nCompressed bits:");
for (l=0; l<len*8; l++) {
bit = (in[l/8]>>(7-l%8))&0x01;
//Serial.print((int)bit);
//if (l%8 == 7) Serial.print(" ");
}
}
void loop() {
char* dump = (char)LoRa.read();
char in[255];
strcpy(in, dump);
char str[] = in;
char cbuf[300];
char dbuf[300];
int len = sizeof(str);
if (len > 0) {
memset(cbuf, 0, sizeof(cbuf));
int ctot = shox96_0_2_compress(str, len, cbuf, NULL);
print_compressed(cbuf, ctot);
memset(dbuf, 0, sizeof(dbuf));
int dlen = shox96_0_2_decompress(cbuf, ctot, dbuf, NULL);
dbuf[dlen] = 0;
float perc = (dlen-ctot);
perc /= dlen;
perc *= 100;
Serial.print(ctot);
Serial.write(",");
Serial.println(dlen);
}
delay(1000);
}
The compiler can only supply the size of an array for you on creation if it has a brace enclosed initializer list. Like this:
int array[] = {1, 2, 3, 4, 5};
If you're doing anything other than that then you need to put a number inside those braces. Since you're making a copy of the array in and that array is 255 char then this one needs to be 255 char as well in order to accommodate.
char str[255] = in;
My comment on your question still stands though. This answer clears your compiler error, but I don't think it is really a solution to your larger problem. But without seeing more of your code and knowing more about it I can't tell much about it. You already have two copies of this data by the time you get to that line. I'm not sure why you think you need to have a third.

C++ AES Encryption getting truncated to 16 characters

I've got a function that I worked on a while ago in C++ that does AES 256 encryption using CBC.
I wrote the method a while ago so I unfortunately can't remember where I got the code from, but I've since found that I have a problem where if the string being encrypted is over 16 characters, its only the first 16 characters of the string that get encrypted.
The code is below:
string Encryption::encryptOrDecrypt(string stringToEncrypt, Mode mode)
{
HelperMethods helperMethods;
try
{
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
unsigned char key[33] = "my_key";
unsigned char iv[17] = "my_iv";
if (mode == Decrypt)
{
stringToEncrypt = helperMethods.base64Decode(stringToEncrypt);
}
vector<unsigned char> encrypted;
size_t max_output_len = stringToEncrypt.length() + 16 - (stringToEncrypt.length() % 16);
//size_t max_output_len = 16 - (stringToEncrypt.length() % 16);
encrypted.resize(max_output_len);
EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv, mode);
// EVP_CipherUpdate can encrypt all your data at once, or you can do
// small chunks at a time.
int actual_size = 0;
EVP_CipherUpdate(ctx,
&encrypted[0], &actual_size,
reinterpret_cast<unsigned char *>(&stringToEncrypt[0]), stringToEncrypt.size());
// EVP_CipherFinal_ex is what applies the padding. If your data is
// a multiple of the block size, you'll get an extra AES block filled
// with nothing but padding.
int final_size = 0;
EVP_CipherFinal_ex(ctx, &encrypted[actual_size], &final_size);
actual_size += final_size;
encrypted.resize(actual_size);
char * buff_str = (char*)malloc(encrypted.size() * 2 + 1);
memset(buff_str, 0, (encrypted.size() * 2 + 1));
char * buff_ptr = buff_str;
size_t index = 0;
for (index = 0; index < encrypted.size(); ++index)
{
buff_ptr += sprintf(buff_ptr, "%c", encrypted[index]);
}
EVP_CIPHER_CTX_cleanup(ctx);
EVP_CIPHER_CTX_free(ctx);
if (mode == Encrypt)
{
string encryptedString = buff_str;
free(buff_str);
return helperMethods.base64Encode(encryptedString.c_str(), encryptedString.length());
}
else
{
string decryptedString = buff_str;
free(buff_str);
return decryptedString;
}
}
catch (exception ex)
{
return stringToEncrypt;
}
}
I've stepped through the code to see where the problem might be and I can't see any reason why, its probably something stupidly simple.
The size_t max_output_len is 768 (the actual string is 752) so this is +16 for padding I believe, but I'm not sure if this should 768 as well but as the method is setting this itself not sure.
The pointer int final_size that gets passed into EVP_CipherFinal_ex becomes 16 when that method completes and the actual_size is also 768 so not sure where the problem is.
I think I've figured the problem, although not 100% sure why this works and the original way doesn't.
I don't believe its a null byte from looking at the content of buffer when debugging but I've changed it to the following which seems to resolve it.
Instead of
string encryptedString = buff_str;
I have changed it to the following
int i = 0;
stringstream encryptedStringStream;
for (i = 0; i < index; i++)
{
encryptedStringStream << buff_str[i];
}
string encryptedString = encryptedStringStream.str();

Padding Issue of Long Hashes

For crypto experts, I have a question that recently came into my mind. So, for example, think that we have a long string of bytes and we want to put that string into a hash function which we may take for the sake of illustration as SHA1. As we know, SHA1 takes inputs in 64 bytes chunks and every hash function afaik needs to pad the message before processing. Now the question is that is it the last chunk that needs to be padded or the whole string? It will matter because at the end of padding we will append the length. Thanks all.
Now the question is that is it the last chunk that needs to be padded or the whole string?
I believe both the things are same. Padding the whole string means padding the last chunk only.
Some pseudocode from good old wiki here
A Look at the code might give you some insights :
Taken from : mattmahoney.net/dc/sha1.c
void SHA1PadMessage(SHA1Context *context)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if (context->Message_Block_Index > 55)
{
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 64)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
SHA1ProcessMessageBlock(context);
while(context->Message_Block_Index < 56)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
}
else
{
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 56)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
}
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = context->Length_High >> 24;
context->Message_Block[57] = context->Length_High >> 16;
context->Message_Block[58] = context->Length_High >> 8;
context->Message_Block[59] = context->Length_High;
context->Message_Block[60] = context->Length_Low >> 24;
context->Message_Block[61] = context->Length_Low >> 16;
context->Message_Block[62] = context->Length_Low >> 8;
context->Message_Block[63] = context->Length_Low;
SHA1ProcessMessageBlock(context);
}

Read/Write SImple BMP Image C++

I am trying to read simple BMP file and without performing any operations I am writing it back again to file.
I don't know where the mistake is in reading the file or writing it back.
I have added padding while reading as well as while writing
-- File-Read --.
std::vector<char> tempImageData;
/*tempImageData.resize(m_bmpInfo->imagesize);
file.seekg(m_bmpHeader->dataoffset);
file.read(&tempImageData[0], m_bmpInfo->imagesize);
file.close();*/
tempImageData.resize(m_bmpInfo->imagesize);
int padding = 0;
while (((m_bmpInfo->width*3+padding) % 4) != 0 )
padding++;
for(unsigned int i = 0 ; i < m_bmpInfo->height ; i++)
{
file.seekg(m_bmpHeader->dataoffset + i*(m_bmpInfo->width*3 + padding));
file.read(&tempImageData[i*m_bmpInfo->width*3], i*m_bmpInfo->width*3);
}
file.close();
//bitmaps are stored as BGR -- lets convert to RGB
assert(m_bmpInfo->imagesize % 3 == 0);
for (auto i = tempImageData.begin(); i != tempImageData.end(); i+=3)
{
m_data_red.push_back(*(i+2));
m_data_green.push_back(*(i+1));
m_data_blue.push_back(*(i+0));
}
-- write code
file.write(reinterpret_cast<const char*>(m_bmpHeader), sizeof(BITMAPFILEHEADER));
file.write(reinterpret_cast<const char*>(m_bmpInfo), sizeof(BITMAPINFOHEADER));
// this is wrong.. format asks for bgr.. we are putting all r, all g, all b
std::vector<char> img;
img.reserve(m_data_red.size() + m_data_green.size() + m_data_blue.size());
for(unsigned int i = 0 ; i < m_data_red.size() ; i++)
{
img.push_back(m_data_blue[i]);
img.push_back(m_data_green[i]);
img.push_back(m_data_red[i]);
}
char bmppad[3] = {0};
for(unsigned int i = 0 ; i < m_bmpInfo->height ; i++)
{
// maybe something is wrong
file.write(reinterpret_cast<const char*>(&img[i*m_bmpInfo->width*3]), m_bmpInfo->width * 3 * sizeof(unsigned char));
file.write(bmppad, 1 * ((4-(m_bmpInfo->width*3)%4)%4) * sizeof(char));
}
file.close();
But the results are weird.
Output image------Input image
As the padding is added to every row, I think you need to change this line:
file.seekg(m_bmpHeader->dataoffset + i*m_bmpInfo->width*3 + padding);
to this:
file.seekg(m_bmpHeader->dataoffset + i*(m_bmpInfo->width*3 + padding));
It also might be easier to save the calculated padding rather than calculating it in two different ways.
Edit:
Without all the code to debug through, it is a bit hard to pinpoint, but there is an error on this line:
file.read(&tempImageData[i*m_bmpInfo->width*3], i*m_bmpInfo->width*3);
you should not have the i* part in the amount you are reading. This means at row 200 you are reading 200 rows worth of data into the array, possibly overwriting the end of the array. once you are more than half way through the image, which is interesting given your output.

Access violation, cant figure out the reason

So, been building this class:
public class BitArray {
public:
unsigned char* Data;
UInt64 BitLen;
UInt64 ByteLen;
private:
void SetLen(UInt64 BitLen) {
this->BitLen = BitLen;
ByteLen = (BitLen + 7) / 8;
Data = new unsigned char(ByteLen + 1);
Data[ByteLen] = 0;
}
public:
BitArray(UInt64 BitLen) {
SetLen(BitLen);
}
BitArray(unsigned char* Data, UInt64 BitLen) {
SetLen(BitLen);
memcpy(this->Data, Data, ByteLen);
}
unsigned char GetByte(UInt64 BitStart) {
UInt64 ByteStart = BitStart / 8;
unsigned char BitsLow = (BitStart - ByteStart * 8);
unsigned char BitsHigh = 8 - BitsLow;
unsigned char high = (Data[ByteStart] & ((1 << BitsHigh) - 1)) << BitsLow;
unsigned char low = (Data[ByteStart + 1] >> BitsHigh) & ((1 << BitsLow) - 1);
return high | low;
}
BitArray* SubArray(UInt64 BitStart, UInt64 BitLen) {
BitArray* ret = new BitArray(BitLen);
UInt64 rc = 0;
for (UInt64 i = BitStart; i < BitLen; i += 8) {
ret->Data[rc] = GetByte(i);
rc++;
}
Data[rc - 1] ^= (1 << (BitLen - ret->ByteLen * 8)) - 1;
return ret;
}
};
just finished writing the SubArray function and went on to test but I get "Access violation: attempted to read protected memory" on the line where GetByte(i) gets called. I tested a bit and it doesn't seem to have anything to do with the data array or i, placing "int derp = GetByte(0)" on the first line of the function produces the same error.
calling GetByte from outside the class works fine, I don't understand whats going on.
the test function looks like this:
unsigned char test[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
BitArray* juku = new BitArray(test, 64);
auto banana = juku->GetByte(7); //this works fine
auto pie = juku->SubArray(7, 8);
You might want to consider creating an array of characters, changing:
Data = new unsigned char(ByteLen + 1);
into:
Data = new unsigned char[ByteLen + 1];
In the former, the value inside the parentheses is not the desired length, it's the value that *Data gets initialised to. If you use 65 (in an ASCII system), the first character becomes A.
Having said that, C++ already has a pretty efficient std::bitset for exactly the situation you seem to be in. If your intent is to learn how to make classes, by all means write your own. However, if you want to just make your life simple, you may want to consider using the facilities already provided rather than rolling your own.