Hi there,

I want to read 1 byte of information, in the form of an array of unsigned chars [1], from a file. I then want to use this piece of data to act as a secret key for a message authentication code I will be performing. The key will be a 20 byte array of unsigned chars [20].

At the moment I have this as my key:
memset( key, 0x0b ,20);

It is basically 0b repeated x 20 to make up a 20 byte key:
0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b

But instead I want to store they key in a file and read it from there rather than hard code it in.

Here is what I am doing at the moment. I have saved '0x0b' in a .dat file, that is the files only content.

std::fstream myFile("/home/adam/Documents/cryptopp/mackeystring.dat",std::ios::app);

myFile.open("/home/adam/Documents/cryptopp/mackeystring.dat");

if (! myFile) // Always test file open
    {
        std::cout << "Error opening output file\n";
        return -1;
    }
   
//char *key;

	std::string keystring;

	getline(myFile,keystring);
	
unsigned char sequence [1];
memcpy(sequence,&keystring,1);

myFile.close();

memset( key, sequence ,20);

But it says that an unsigned char etc can not be used as an integer in the 2nd command of the memset. Although it worked fine when '0x0b' was hard coded into it. The code is opening and getting some data ok from the file, but I just need it converted to an array of unsigned chars ok, and for it to be accepted as my key.


Basically I want to replace 0x0b with the variable, sequence, and retrieve the value of 'sequence' from a file, instead of having it hard coded in. And its value should be a 20 byte array of unsigned chars: ie = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b

Any help with this would be great,
Thanks.

Recommended Answers

All 10 Replies

1. You have a binary file. Don't use getline to get data from it - getline gets a line from a text file; use read():

unsigned char key[20];
fstream f(".....",ios::binary);
// No need to open file explicitly 
// when the filename is specified in the constructor.
if (f.is_open()) // or simply: if (f)
{
    if (f.read((char*)key,sizeof key))
    {
    // you get this data!
    }
}

The 1st arg of read() must be char* pointer, so use cast op if you want to read into unsigned char array.

2. Have a look at this (incorrect) code fragment:

std::string keystring;
...
unsigned char sequence [1];
memcpy(sequence,&keystring,1);

You never get the 1st byte of keystring contents! Right construct:

memcpy(sequence,keystring.data(),1);

An address (pointer to) of std::string object is not the same thing as this string data address. It's an address of a string object header. So you get a byte from this header but it's absolutely uninteresting result for you...

Many thanks for the reply, I will just read the whole key in one go now so have changed the .dat file to read 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b for the 20 byte key.

Where should I use the op cast to convert between an unsigned char and char*? And if you could type out for me what that op cast command should look like that would be great.

Was also slightly confused about the 2nd if statement, whether that was just to test that the type it is reading is correct, or whether it is actually doing some sort of reading itself.

Where you put the comment of //you get this data!
I have put the line: myFile.read (key,20);

Which, as expected, gives conversion errors as it not type char*

So would I need to change 'key' to be a variable of char* and then do the opcast on it to get my 20 byte unsigned char array called key?

I don't understand why you don't understand...

Look at my code snippet. Substitute your stream variable (myFile) instead of mine one (f).

if (myFile.read((char*)key,20))
{
    // Well, you gOt your key! It's here, in key unsigned char array now!
    // (char*)key - it's a proper cast here!
    .... don't worry, process your key as unsigned char if you wish...

The stream.read() returns a reference to the stream. You can use a stream class object reference in conditional expression directly: it's true if a previous operation was successful. In actual fact there are a chain of casting here, but what does in matter to us?..

I hope, you feel at home not only in copy/paste environment...

Thanks,

I have now got it reading ok from the file into the array of unsigned chars.

The only problem is that it is interpreting the key different than it should be.

The content of my file is:
0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b

When I print out the contents of the unsigned char array it produces:

30 62 30 62 30 62 30 62 30 62 30 62 30 62 30 62 30 62 30 62

So I maybe it is storing each '0' and each 'b' seperately as 1 byte in each slot of the unsigned char array?

Where as my key is basically 0x0b repeated 20 times. So 0b is 1 byte. How do I get it to read 2 characters as being 1 byte, rather than each character being a byte? Cheers.

Please, post your current code now (especially key writing part). You wrote a textual representation of repeated "0b" pair (exactly 30 62 in ASCII) instead of packed byte '0x0b').

Please, post your current code now (especially key writing part). You wrote a textual representation of repeated "0b" pair (exactly 30 62 in ASCII) instead of packed byte '0x0b').

I have a file called mackeystring.dat and its contents is exactly:
0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b

NB: the key, as exactly given by the test vector that I am using, using hmac-sha from rfc2202 is:
0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b

unsigned char key[20];

fstream myFile ("/home/adam/Documents/cryptopp/mackeystring.dat", ios::binary);
myFile.open("/home/adam/Documents/cryptopp/mackeystring.dat");

if (myFile)
{

myFile.read((char*)key,sizeof key);
}

else printf("error opening file");

myFile.close();

printf("\nFILE CONTENTS: \n");

for (int i=0; i<20; i++)
printf(" %02x ", key[i]);

//full content of key= 30  62  30  62  30  62  30  62  30  62  30  62  30  62  30  62  30  62  30  62 

//this is where the 20 byte key is used:
HMAC<SHA1> hmac( key, sizeof(key ) );
...
...

Previously I used: memset (key, 0x0b, 20);
to get my key, and if gave the correct result for my hmac-sha calculation, but have taken this out to retrieve it from the file instead.

So could either have the block of 0x0b stored in the file, and then put that 1 byte unsigned char into the memset, or just have the full key written to the file, which is what I have done now. Because when I try to replace 0x0b in the memset, with a unsigned char variable, it says invalid conversion between unsigned char and int for the memset expected values.

When I put the 0x in my ,dat file, both the 0 and the x are being read as a characters individually (ie 30 78)so took it out.

It works when I use the test vector with the string value of Jefe being used as the key in the file. As each character is one byte. But when I have the 0b pairs in, it does not give the correct output when I use that value for my calculation using the key.

Thanks again.

Wait a bit;): there are two different cases (let's use C++ notation):

1. mackeystring.dat contains TEXT data "0b0b... and so on 0b" (if so why it has .dat extension?)
2. mackeystring.dat contains BINARY data "\x0b\x0b...\x0b" (if so you can't print these 30 60 pairs).

In case#1 you must convert this data in binary form after reading (pack two byte values into a single byte). It's a simple limbering-up for beginner...

In case#2 you may place the file contents in the key array directly. No problems...

Happy end of the thread of this story?..

So in case#2 do you mean that the contents of my file should be:

\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b ?

I have done that and it treats each '\', 'x', '0' and 'b' as a seperate character and gives a 2 character representation of each. So basically the is up to 80 odd characters needing one byte of storage....when I just want each slot of my array to have the content of '0x0b'.

Previously, I just used memset(key, 0x0b, 20)

Which when printed using printf("%02x, key) etc.. in a for loop,

GIves: 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b

So what I am doing now is not giving me the same contents of my previous key array. What am I doing wrong?! Is it the code itself, or the way I am storing the data in the file?!

Just made a quick experiemental change and if I create an integer variable and give it the value of 0x0b

and then do:

memset(key, integer, 20);

it works.

So maybe I should be trying to read the content of 0x0b from the file and saving it as an integer? But the the same problem as it treating each character individually may arise rather than a block?

Have you ever seen any C or C++ textbook?
In C and C++ "\x0b\x0b" denotes two-bytes string with byte value '\x0b' (11) - plus zero byte, but it's not interesting now.

Exactly, I want to know:
1. "the way you are storing the data in the file".
2. What did you want to store in the file - 20 bytes with values 13 (hexadecimal 0b) or 40 bytes of a text "0b0b...0b" - or what else?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.