I am trying to write an AES key to a file then read it later. I'm using the Crypto++ library, and the AES key is initialized as follows. Below, byte
is a typedef of unsigned char
.
byte key[CryptoPP::AES::MAX_KEYLENGTH]
The key is 32 bytes long. I try to write it into a file with this:
FILE* file = fopen("C:\\key", "wb");
fwrite(key, 1, sizeof(key), file);
fclose(file);
And recover it using:
FILE* read_file = fopen("C:\\key", "rb");
fseek(read_file, 0, SEEK_END);
long int size = ftell(read_file);
fclose(read_file);
read_file = fopen("C:\\key", "rb");
unsigned char * in = (unsigned char *)malloc(size);
byte readed_key = fread(in, sizeof(unsigned char), size, read_file);
fclose(read_file);
if (key == readed_key)
{
cout << "this is the right key !";
}
free(in);
However, I get an error message:
incompatible operand types : byte* and byte.
I don't understand why, since readed_key
and key
are initialized with byte
and not byte*
.
I looked at AES on the Crypto++ wiki, and the key is generated as follow. I figured out that I was just creating the key (not generating it):
SecByteBlock key(0x00, AES::MAX_KEYLENGTH);
rnd.GenerateBlock( key, key.size() );
With that I can't use
std::vector<byte> key(32);
rnd.GenerateBlock(key, key.size());
Because rnd.Generateblock
can't convert std::vector< byte > into byte*
This is driving me crazy....
How to read and write an AES key to and from a file?
I'm going to avoid your code since its mostly C code. Andrew pointed out some of the problems with it, so there's no sense in rehashing it. Instead I'll show you the Crypto++ and C++ way of doing things. I'll also discuss SecByteBlock
a little.
Here's the Crypto++ way to read the data into a byte array using sources and sinks. You can read more about them at Pipelines in the Crypto++ wiki.
byte key[CryptoPP::AES::MAX_KEYLENGTH];
FileSource fs("C:\\key.bin", true, new ArraySink(key, sizeof(key)));
Here's the Crypto++ way to write data to a file using sources and sinks.
byte key[CryptoPP::AES::MAX_KEYLENGTH];
ArraySource as(key, sizeof(key), true, new FileSink("C:\\key.bin"));
Here's the C++ way to read the data into a byte array using streams. Its taken from Reading and writing binary file
byte key[CryptoPP::AES::MAX_KEYLENGTH];
std::ifstream fs("C:\\key.bin", std::ios::binary);
fs.read(key, sizeof(key));
Here's the C++ way to write data to a file using streams.
byte key[CryptoPP::AES::MAX_KEYLENGTH];
std::ofstream fs("C:\\key.bin", std::ios::binary);
fs.write(key, sizeof(key));
std::vector<byte> key(32); rnd.GenerateBlock(key, key.size());
Because rnd.Generateblock can't convert
std::vector< byte >
intobyte*
. This is driving me crazy....
Here, you need a non-const pointer to the first element. Take the address of the first element in your vector. The same would apply to a std::string
.
std::vector<byte> key(32);
rnd.GenerateBlock(&key[0], key.size());
Since the key is sensitive, you should use a SecByteBlock
. It zeroizes the key from memory once you are done using it.
Generally speaking, if the information is sensitive, then you want to use a SecBlock<T>
. In the case of SecByteBlock
, T
is a byte
and there's a typedef for SecByteBlock
. But you can make a SecBlock<T>
out of anything.
Here's the Crypto++ way to read the data into a SecByteBlock
using sources and sinks.
SecByteBlock key(AES::MAX_KEYLENGTH);
FileSource fs("C:\\key.bin", true, new ArraySink(key.begin(), key.size()));
SecByteBlock
can initialize elements to a known value upon construction. You are using the feature below. All elements are initialized to 0x00
.
SecByteBlock key(0x00, AES::MAX_KEYLENGTH);
rnd.GenerateBlock(key, key.size());
Since you are overwriting the elements immediately with random data, you should forgo initialization. Just ask for an uninitialized block of memory:
SecByteBlock key(AES::MAX_KEYLENGTH);
rnd.GenerateBlock(key, key.size());