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();
Related
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.
I'm working on an Arduino Due, trying to use DMA functions as I'm working on a project where speed is critical. I found the following function to receive through serial:
uint8_t DmaSerial::get(uint8_t* bytes, uint8_t length) {
// Disable receive PDC
uart->UART_PTCR = UART_PTCR_RXTDIS;
// Wait for PDC disable to take effect
while (uart->UART_PTSR & UART_PTSR_RXTEN);
// Modulus needed if RNCR is zero and RPR counts to end of buffer
rx_tail = (uart->UART_RPR - (uint32_t)rx_buffer) % DMA_SERIAL_RX_BUFFER_LENGTH;
// Make sure RPR follows (actually only needed if RRP is counted to the end of buffer and RNCR is zero)
uart->UART_RPR = (uint32_t)rx_buffer + rx_tail;
// Update fill counter
rx_count = DMA_SERIAL_RX_BUFFER_LENGTH - uart->UART_RCR - uart->UART_RNCR;
// No bytes in buffer to retrieve
if (rx_count == 0) { uart->UART_PTCR = UART_PTCR_RXTEN; return 0; }
uint8_t i = 0;
while (length--) {
bytes[i++] = rx_buffer[rx_head];
// If buffer is wrapped, increment RNCR, else just increment the RCR
if (rx_tail > rx_head) { uart->UART_RNCR++; } else { uart->UART_RCR++; }
// Increment head and account for wrap around
rx_head = (rx_head + 1) % DMA_SERIAL_RX_BUFFER_LENGTH;
// Decrement counter keeping track of amount data in buffer
rx_count--;
// Buffer is empty
if (rx_count == 0) { break; }
}
// Turn on receiver
uart->UART_PTCR = UART_PTCR_RXTEN;
return i;
}
So, as far as I understand, this function writes to the variable bytes, as a pointer, what is received as long as is no longer than length. So I'm calling it this way:
dma_serial1.get(data, 8);
without assigning its returning value to a variable. I'm thinking the received value is stored to the uint8_t* data but I might be wrong.
Finally, what I want to do is to check if the received data is a certain char to take decisions, like this:
if (data == "t"){
//do something//}
How could I make this work?
For comparing strings like intended by if (data == "t"), you'll need a string comparison function like, for example, strcmp. For this to work, you must ensure that the arguments are actually (0-terminated) C-strings:
uint8_t data[9];
uint8_t size = dma_serial1.get(data, 8);
data[size]='\0';
if (strcmp(data,"t")==0) {
...
}
In case that the default character type in your environment is signed char, to pass data directly to string functions, a cast is needed from unsigned to signed:
if (strcmp(reinterpret_cast<const char*>(data),"t")==0) {
...
}
So a complete MVCE could look as follows:
int get(uint8_t *data, int size) {
data[0] = 't';
return 1;
}
int main()
{
uint8_t data[9];
uint8_t size = get(data, 8);
data[size]='\0';
if (strcmp(reinterpret_cast<const char*>(data),"t")==0) {
cout << "found 't'" << endl;
}
}
Output:
found 't'
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.
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.
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);