How to handle encrypted string? - c

I am trying to make a simple application, which is able to encrypt and decrypt some simple data. CryptEncrypt is working fine. The string to encrypt is: This is a sample string.. The encrypted data for this string is: ¼╩b╒áó√ $~ë▀i▐└╕ ]Φwµσ╨|V╜▐µáïÅ╚
So far so good.
After i have the encrypted text, i copy it to another string. This string will be used at the decryption. For some reason only the half of the string wil be copied in the new buffer,a nd therefore it can't be decrypted.
No matter how i try. I'm assumeing that in the encrypted string there are some special characters, and therefore it won't copied as expected. For example if i use sprintf(teststring,"%s",Encryptedstring); it will also copy only half of the string.
Is there a way to make CryptEncrypt encrypt the data in a hex form by default?
How should i copy my string correctly?

You are making a basic mistake:
You are handing a c-string (I cannot say whether with or without the terminator) to CryptEncrypt and somehow expect magically to get a valid c-string of the same length back.
Things just don't work that way, the output of any good encryption-function looks like a pseudo-random binary blob, maybe with embedded 0-bytes, maybe not, and unlikely to have a terminating 0-byte.
Case in point, the output you gave is considerably longer than the input (The last part is probably garbage picked up due to missing 0-terminator).
The solution: Properly handle arbitrary binary data as arbitrary binary data (memcpy for copying).
If you want, you can encode it into some textual representation to get a string, but that's an extra step needing more space and certainly not the task of CryptEncrypt.

My advice is that when you talk about encryption, do not talk in terms of strings. Your string is just a raw data block to an encryption function so deal with it accordingly. The problem with dealing the data as string is that string tends to terminate if a null character is found and there is every possibility that you will get null byte in encrypted block.
This is why string functions dont work with encrypted data. If you want to copy data from buffer to another buffer, use memcpy instead of sprintf or strcpy.

I guess that sprintf will stop the copy if it encounters a '\0' charcater. You should use memcpy

Related

Difficulties understanding how to take elements from a file and store them in C

I'm working on an assignment that is supposed to go over the basics of reading a file and storing the information from that file. I'm personally new to C and struggling with the lack of a "String" variable.
The file that the program is supposed to work with contains temperature values, but we are supposed to account for "corrupted data". The assignment states:
Every input item read from the file should be treated as a stream of characters (string), you can
use the function atof() to convert a string value into a floating point number (invalid data can be
set to a value lower than the lowest minimum to identify it as corrupt)."
The number of elements in the file is undetermined but an example given is:
37.8, 38.a, 139.1, abc.5, 37.9, 38.8, 40.5, 39.0, 36.9, 39.8
After reading the file we're supposed to allow a user to query these individual entries, but as mentioned if the data entry contains a non-numeric value, we are supposed to state that the specific data entry is corrupted.
Overall, I understand how to functionally write a program that can fulfill those requirements. My issue is not knowing what data structure to use and/or how to store the information to be called upon later.
The closest to an actual string datatype which you find in C is a sequence of chars which is terminated by a '\0' value. That is used for most things which you'd expect to do with strings.
Storing them requires just sufficent memory, as offered by a sufficiently large array of char, or as offered by malloc().
I think the requirements of your assignment would be met by making a char array as buffer, then reading in with fgets(), making sure to not read more than fits into your array and making sure that there is a '\0' at the end.
Then you can use atof() on the content of the array and if it fails do the handling of corrupted input. Though I would prefer sscanf() for its better feedback via separate return value.

Serializing strings in C

I'm serializing structs into byte-streams. My method is simple:
pack all ints in little endian order and copy strings including the null terminator. The other side has to statically know how to unpack the byte-stream, there is no additional metadata.
My problem is, that I do not know how to handle the the NULL pointer?
I need to send something, because there is no additional metadata in the stream.
I considered the following two options:
Send a '\0' and make the receiving side interpret it as NULL in any case
Send a '\0' and make the receiving side interpret it as '\0' in any case (alloc a byte)
Send a special character representing char* str == NULL, e.g. ETX, EOT, EM ?
What do you think?
It looks like you are currently trying to tell the receiving end that the end of the serialized string has been reached by passing it a special character. There are a million cases that can screw you over with this:
What if your struct contains a byte that is equal to that special character. Escape it with another special character. What if your struct contains a byte sequence that is equal to your escape character followed by your special character, check for that too?
Yeah it's doable, but I think that's not a very good solution and you'll have to write a parser to look for the escape character and then anyone who takes a look at the code later will spend two hours trying to figure out what's going on.
(tl;dr) Instead... just make the first 32 bits of the serialized string equal to the number of bytes in the string. This only costs 4 bytes per serialization, solves all your problems, you won't have to write a parser or worry about special characters, and will make it a lot easier on the next guy who gets to read through your code!
edit
Thanks to JeremyP I've just realized that I didn't really answer your question. Send one of these guys for every string:
struct s_str
{
bool is_null;
int size;
char* str;
};
If it's null, simply set is_null to true and you don't really have to worry about the other two.
If it's size zero, set is_null to false and size to zero.
If str contains just a '\0', set is_null to false, size to one, and str[0] to '\0'
In my opinion, this might not be the most memory efficient way (you could probably save a byte somewhere somehow) but is definitely quite clear in what you're doing, and again the next guy that comes along will like this a lot more.
Do not do this. use some extra bytes to store length and concatenate with your data string. The receiver end can check the length to know how much it should read into his local buffer.
It depends on the significance of the pointer in your protocol.
If the pointer is significant, i.e. it is needed for the recipient to know how to rebuild the struct, then you need to send something. It could be either a byte with 0/non-zero to indicate existence, or an integer that indicates the number of bytes pointed to by the pointer.
Example:
struct Foo {
int *arr,
char *text
}
Struct Foo could be serialized like this:
<arr length>< arr ><text length>< text >
4 bytes n bytes 4 bytes n bytes
I would advise you to use an existing library for serialization. I can think of two at the moment: tpl and gwlib's gwser.
About tpl:
You can use tpl to store and reload your C data quickly and easily.
Tpl works with files, memory buffers and file descriptors so it's
suitable for use as a file format, IPC message format or any scenario
where you need to store and retrieve your data.
About gwlib, see the link, it's not very verbose, but it provides a few usage examples.

C CSV API for unicode

I need a C API for manipulating CSV data that can work with unicode. I am aware of libcsv (sourceforge.net/projects/libcsv), but I don't think that will work for unicode (please correct me if I'm wrong) because don't see wchar_t being used.
Please advise.
It looks like libcsv does not use the C string functions to do its work, so it almost works out of the box, in spite of its mbcs/ws ignorance. It treats the string as an array of bytes with an explicit length. This might mostly work for certain wide character encodings that pad out ASCII bytes to fill the width (so newline might be encoded as "\0\n" and space as "\0 "). You could also encode your wide data as UTF-8, which should make things a bit easier. But both approaches might founder on the way libcsv identifies space and line terminator tokens: it expects you to tell it on a byte-to-byte basis whether it's looking at a space or terminator, which doesn't allow for multibyte space/term encodings. You could fix this by modifying the library to pass a pointer into the string and the length left in the string to its space/term test functions, which would be pretty straightforward.

How can I parse text input and convert strings to integers?

I have a file input, in which i have the following data.
1 1Apple 2Orange 10Kiwi
2 30Apple 4Orange 1Kiwi
and so on. I have to read this data from file and work on it but i dont know how to retrieve the data. I want to store 1(of 1 apple) as integer and then Apple as a string.
I thought of reading the whole 1Apple as a string. and then doing something with the stoi function.
Or I could read the whole thing character by character and then if the ascii value of that character lies b/w 48 to 57 then i will combine that as an integer and save the rest as string? Which one shall I do? Also how do I check what is the ASCII value of the char. (shall I convert the char to int and then compare, or is there any inbuilt function?)
How about using the fscanf() function if and only if your input pattern is not going to change. Otherwise you should probably use fgets() and perform checks if you want to separate the number from the string such as you suggested.
There is one easy right way to do this with standard C library facilities, one rather more difficult right way, and a whole lot of wrong ways. This is the easy right way:
Read an entire line into a char[] buffer using fgets.
Extract numbers from this line using strtol or strtoul.
It is very important to understand why the easier-looking alternatives (*scanf and atoi) should never be used. You might write less code initially, but once you start thinking about how to handle even slightly malformed input, you will discover that you should have used strtol.
The "rather more difficult right way" is to use lex and yacc. They are much more complicated but also much more powerful. You shouldn't need them for this problem.

Search and replace string and ignore null byte character

I'm working on a C program that uses NFQUEUE to filter traffic for another application. One of the things I need to do is replace a string contained within a packet, with another string.
The problem is, the packets seem to contain the null terminator byte randomly (in the middle of the string). This means that most solutions I see, using strstr(), don't work. I need to find something similar that doesn't stop upon reaching a null terminator byte, but rather allows for a length to be specified and uses that instead. (nfq_get_payload() returns a length.)
I've looked at replacing the null bytes with another byte before performing the replace, and then restoring the null bytes before the packet is sent off. The problem with that approach is there's a chance the packet could contain the character, so that wouldn't be the best approach. I suppose I could also find a random byte that is not contained within the packet, but I'd rather avoid doing all that.
edit: Both the original string and replacement string are the same length, which is 13 characters.
You might be satisfied with memchr if finding one character can work for you. Otherwise, you would have to make a memmem implementation yourself or find one online.
Be aware that string-searching algorithms (because that's what memmem is) can have a wide range of performance characteristics, so you want to find one based on a performant algorithm (e.g. this one looks acceptable, but your mileage may vary).

Resources