Andiana
Andiana

Reputation: 1952

Sizeof array auto changed when passed into function in Visual C++

I am using the library Crypto++ for encrypting/decrypting data. The official page is https://www.cryptopp.com. I am following this tutorial. It shows how to use block cipher with Crypto++. You can see this part with find keyword "using block cipher".

I can run the demo smoothly. They encrypt the data using the key, then decrypt data using the same key. I want to split the code to an encrypt() and a decrypt() function. You can see my encrypt() function below.
The include part:

#include "E:\Working\Improve\CPP\cryptopp565\osrng.h"
using CryptoPP::AutoSeededRandomPool;

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;

#include <string>
using std::string;

#include <cstdlib>
using std::exit;

#include "E:\Working\Improve\CPP\cryptopp565\cryptlib.h"
using CryptoPP::Exception;

#include "E:\Working\Improve\CPP\cryptopp565\hex.h"
using CryptoPP::HexEncoder;
using CryptoPP::HexDecoder;

#include "E:\Working\Improve\CPP\cryptopp565\filters.h"
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::StreamTransformationFilter;

#include "E:\Working\Improve\CPP\cryptopp565\aes.h"
using CryptoPP::AES;

#include "E:\Working\Improve\CPP\cryptopp565\ccm.h"
#include "E:\Working\Improve\CPP\cryptopp565\modes.h"
using CryptoPP::ECB_Mode;
#include <fstream>

#include "assert.h"


Code body:

// My encrypt function
void encrypt(byte cbCipherText[AES::BLOCKSIZE], byte *plainText,
             byte key[AES::DEFAULT_KEYLENGTH], int sizeKey) {
  int size = sizeof(key);
  ECB_Mode<AES>::Encryption Encryptor(key, sizeKey);

  Encryptor.ProcessData(cbCipherText, plainText, sizeof(plainText));
}

void main() {
  byte PlainText[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o',
                      'r', 'l', 'd', 0x0, 0x0, 0x0, 0x0, 0x0};

  byte key[AES::DEFAULT_KEYLENGTH];
  ::memset(key, 0x01, AES::DEFAULT_KEYLENGTH);

  // Encrypt data
  int size = sizeof(key);
  int default = AES::DEFAULT_KEYLENGTH;
  ECB_Mode<AES>::Encryption Encryptor(key, size);

  // Next three lines are tutorial's code for encrypt
  byte cbCipherText[AES::BLOCKSIZE];
  Encryptor.ProcessData(cbCipherText, PlainText, sizeof(PlainText));
  ECB_Mode<AES>::Decryption Decryptor(key, sizeof(key));

  // Next two lines are my code to call the encrypt() function, I "cloned" the
  // code
  // from above three line!. Comment out them we will have the code like the
  // demo.

  byte myCipherText[AES::BLOCKSIZE];
  encrypt(myCipherText, PlainText, key, size);

  // Decrypt
  byte cbRecoveredText[AES::BLOCKSIZE];

  Decryptor.ProcessData(cbRecoveredText, cbCipherText, sizeof(cbCipherText));

  //    std::string PlainText ="Voltaire said, Prejudices are what fools use for
  //reason";

  cout << endl << "Recovered text: " << cbRecoveredText << endl;
  getchar();
}

The key was created with value \x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1. In the demo code, the key's value is never changed and its size is always 16. When I call my encrypt() function and pass key to it, the key size (sizeof(key)) is 16 when it was created, but after passed to function, the length is always 4 (!). And the key value is x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1ĂŒĂŒĂŒĂŒĂŒĂŒĂŒĂŒHello World (!!!). Therefore, my code always gets the error "AES: 4 is not valid key length" if I jump into the function. I don't understand why this happened and how to fix it. Any help would be appreciated!

Upvotes: 0

Views: 105

Answers (2)

Andiana
Andiana

Reputation: 1952

Thank for @krzaq comment. I fixed my problem. Problem is: key's size and plainText's sizes must be passed as a number to function. You cannot retrieve size by use sizeof() after passing the pointer into function.

I fixed the code:

// My encrypt function
void encrypt(byte cbCipherText[AES::BLOCKSIZE], byte *plainText,
             byte key[AES::DEFAULT_KEYLENGTH], int sizeKey, int sizeKey) {
  int size = sizeof(key);
  ECB_Mode<AES>::Encryption Encryptor(key, sizeKey);

  Encryptor.ProcessData(cbCipherText, plainText, textKey);
}
...
void main() {
 ...
  int sizeText = sizeOf(plainText);
  encrypt(myCipherText, PlainText, key, sizeKey, sizeText);

...
  }

And now its worked!

Upvotes: 1

krzaq
krzaq

Reputation: 16431

Top-level arrays in function prototypes are nothing more than hints to the programmer, if that.

The following prototypes are exactly the same

void foo(int x[20]);
void foo(int x[]);
void foo(int* x);

In other words, with sizeof(x), you're measuring the size of a pointer.

You can avoid this using std::array instead (but you'll probably want to avoid passing it by value).

If you absolutely need to work with a C-like API, you need to pass the number of elements in the array as a separate parameter. There's no standard way of getting it from a pointer.

Upvotes: 3

Related Questions