I'm trying to create a long string that is produced out of encrypted substrings. For the encryption I'm using AES128 and libmcrypt. The code is working, but I get a shorter output then I should and a beeping sound. I guess it's because I'm using strlen, but I have no idea, how I can avoid that. I will be very grateful for some suggestions. Here is my code:
char *Encrypt( char *key, char *message){
static char *Res;
MCRYPT mfd;
char *IV;
int i, blocks, key_size = 16, block_size = 16;
blocks = (int) (strlen(message) / block_size) + 1;
Res = calloc(1, (blocks * block_size));
mfd = mcrypt_module_open(MCRYPT_RIJNDAEL_128, NULL, "ecb", NULL);
mcrypt_generic_init(mfd, key, key_size, IV);
strncpy(Res, message, strlen(message));
mcrypt_generic(mfd, Res, block_size);
//printf("the encrypted %s\n", Res);
mcrypt_generic_deinit(mfd);
mcrypt_module_close(mfd);
return (Res);
}
char *mkline ( int cols) {
int j;
char seed[] = "thesecretmessage", key1[]="dontusethisinput", key2[]="abadinputforthis";
char *encrypted, *encrypted2, *in = malloc(cols * 16);
encrypted = Encrypt(key1, seed);
sprintf(in, "%s", encrypted);
encrypted2= Encrypt(key2, encrypted);
printf("encrypted2 before for-loop %s\n", encrypted2);
printf("encrypted2 before for loop len %d\n", strlen(encrypted2));
for (j=1; j<cols; j++) {
strcat(in, encrypted2);
memmove(encrypted2, Encrypt(key2, encrypted2),strlen(seed));
printf("encrypted2 %s on position %d\n" , encrypted2,j);
printf("encrypted2 len %d\n", strlen(encrypted2));
}
free(encrypted);
free(encrypted2);
return in;
}
int main(int argc, char *argv[]) {
char *line = mkline(15);
printf("line %s\n", line);
printf("line lenght %d\n", strlen(line));
return 0;
}
You get the beep sound because you are printing control character.
Also strlen return the size until the first '\0' character (because strings are zero terminated). That's why you get length less than you expect since the encrypted message may contain zeroes.
You can do something like this to return the result length:
char *Encrypt(const char *key, const char *message, int *result_len)
{
*result_len = blocks * block_size;
}
Also
memmove(encrypted2, Encrypt(key2, encrypted2),strlen(seed));
This line should produce a memory leak since every time you call Encrypt you call calloc (allocate new memory) which you need to free after you are done.
You probably should use memcpy, memmove is primarly used if there is a chance destination and source may overlap.
The encrypted string you are trying to print contains a stream of bytes where the value of the individual byte ranges from 0 to 255. Because you are using a cryptographically secure algorithm, the distribution of values is very close to even.
Since you are trying to print the encrypted string through a console, the console interprets some of the bytes as control characters (see Bell character) that are unprintable but have other effects instead, such as playing beeps.
Furthermore, strlen isn't doing what you think it should be doing because the encrypted string is not null-terminated, but instead contains zeroes amongst other bytes and they have no special meaning unlike in NULL terminated strings. You need to store the length of the string elsewhere.
Simple, you are treating binary output (any byte value) directly as printable text. Any character wit a code point below 32 (hex 20) isn't. E.g. the ASCII value for BELL (look it up) could be meaningful to you. Print the resulting bytes in hexadecimals and you should be ok.
I should like to add that in general it is good practice to clear any memory that held the plaintext/unencrypted message after you encrypt it if you can. This is not good coding practice, but good cryptology practice.
This can be done by:
memset(buffer, 0, length_of_buffer);
Don't worry, that won't be optimized out by your compiler. It's actually not smart enough to tell if you'll be using that area again or not.
Related
I would like to write a program in C that gets the file content via stdin and reads it line by line and, for each line, converts it to an array of 8-bit integer values.
I also would like to be able to do the reverse process. After working with my array of 8-bit values, I would like to convert it again to "lines" that would be organized as a new buffer.
So basically, I would like to convert a char * line to an int array[] and back (an int array[] to a char * line) while keeping the consistency, so when I create the file again out of the conversions, the file is valid (and by valid I mean, the conversion from int array[] to char * line generates the same content of the original char * line, while reading each line of the stdin.
My code is currently as follows:
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *stream;
char *line = NULL;
size_t len = 0;
ssize_t read;
stream = stdin;
if (stream == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, stream)) != -1) {
char * array = line_to_array(line);
// here I include the rest of my code
// where I am going to use the generated array
// ...
}
free(line);
fclose(stream);
exit(EXIT_SUCCESS);
}
The line_to_array function would be the one to convert the "line" content to the array of integers. In a second file, I would just do the opposite.
The mechanics of the process would be like this:
The first program (first.c) would receive a file content via stdin. By reading it using getline, I would have each line to convert to an array of integers and send each line to a second program (second.c) that would convert each array to a char * buffer again and the reconstruct the file.
In the terminal, I would run it like this:
./first | ./second
I appreciate any help on this matter.
Thank you.
I believe you may already know that a name of array is a kind of constant pointer. You could verify the fact from following code:
char hello[] = "hello world!";
for( int idx=0; *(hello + idx) != 0; idx++ )
{
printf("%c", *(hello + idx));
}
printf("\n");
So, there are no reason to convert character pointer to array. For your information, A char variable is a 8bit data in C, this can contain a integer value which is represent a character: 65 represent 'A' in ASCII code.
Secondly, this link may help you to understand how to convert between c string and std::string.
On second thought, may your input file is UNICODE or UTF-8 encoded file which is using multi-byte character code. In that case, you may not able to use getline() to read the string from the file. If so, please refer this question: Reading unicode characters.
I wish following code assist you to understand char type, array and pointer in C/C++:
std::string hello("Hello world");
const char *ptr = hello.c_str();
for( int idx=0; idx < hello.size(); idx++ )
{
printf("%3d ", *(ptr + idx));
}
printf("\n");
std::string hello("Hello world");
const char *ptr = hello.c_str();
for( int idx=0; idx < hello.size(); idx++ )
{
printf("%3d ", ptr[idx]);
}
printf("\n");
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Im Encrypting the Original Messages using XOR algorithm by following code in C program. And Finally it gives another different value that message has encrypted. It should return same length even after the message has encrypted.
But, Using strlen(encrypted) it gives less value than original message length. I couldn't recognize why the length of XOR encrypted message is showing less than the original message length. Please find the following the code to solve my problem.
Thanks in Advance!
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* XORCipher(char* data, char* key, int dataLen, int keyLen) {
char* output = (char*)malloc(sizeof(char)*dataLen);
for(int i = 0; i < dataLen; ++i) {
output[i] = data[i] ^ key[i % keyLen];
}
return output;
}
int main(){
char *msg = "This is a Message from Boss";
char *key = "nandha";
int dataLen = strlen(msg);
int keyLen = strlen(key);
char *encrypt = XORCipher(msg,key,dataLen,keyLen);
printf("\nEncrypted msg is :\n %s",(char*)encrypt);
//The Length of encrypted char size is showing wrongly.
printf("size of Encrypted msg is: %d\n",strlen(encrypt));
encrypt = XORCipher(encrypt,key,strlen(encrypt),keyLen);
printf("\nOriginal msg converted is : %s\n",encrypt);
return 0;
}
When you perform these XOR operations on your string, the resulting values could fall outside the range of printable characters. In particular, if a plaintext character happens to match the key character used to encode it the result will be 0.
In C, a string is actually a sequence of characters terminated by a null byte, i.e. a byte with value 0. Any function that operates on strings looks for this byte to denote the end of the string.
Because your encoding can generate null bytes, your encrypted message is not a string but an array of bytes. Attempting to use a string function on the encrypted message can cause it to stop processing in the middle of the message if it contains a null byte. If the message does not contain a null byte, these string functions will continue to read past the end of the character array until it finds one. Reading past the end of an array or dynamically allocated block of memory invoked undefined behavior.
You need some other way to know how long the encrypted message is. In the case of the XOR encoding you're doing this is easy: the length of the ciphertext is the same as the length of the plaintext. So when decoding, pass in dataLen for the ciphertext length. To print the ciphertext, you need to loop through the bytes and print each one individually rather that trying to print it as a string (which it is not).
Also, after you've decoded, you still don't have a string because there was no null terminating byte added to the end of the decrypted message. You can do this manually after calling decrypting:
// pass in plaintext length as ciphertext length since they are the same
encrypt = XORCipher(encrypt,key,dataLen,keyLen);
// null terminate decrypted string
encrypt[dataLen] = '\0';
The buffer allocated inside of XORCipher doesn't currently allocate enough space for the null terminator, so you need to increase this by 1 to allow for this:
// no need to cast the return value of malloc
// sizeof(char) is guaranteed to be 1, so no need to multiply by it
char* output = malloc(dataLen + 1);
C strings are character arrays that are null terminated. When you allocate your encrypted array with the length of the string, you don't leave room for null termination, so strlen is unable to tell when the string ends, thinking the string ends outside of the actual memory that you allocated. This modification to your xor function will make it work.
char* XORCipher(char* data, char* key, int dataLen, int keyLen) {
char* output = (char*)malloc(sizeof(char)*dataLen+1);
output[dateLen] = 0;
for(int i = 0; i < dataLen; ++i) {
output[i] = data[i] ^ key[i % keyLen];
}
return output;
}
Additionally, if you're xor function gives 0 as an output, strlen will see that as the end of the string, which would give you a string length shorter than the expected output.
Update: I have tested the code and it works.
char* XORCipher(char* data, char* key, unsigned long dataLen, unsigned long keyLen) {
char* output = (char*)malloc(sizeof(char)*dataLen+1);
output[dataLen] = 0;
for(int i = 0; i < dataLen; ++i) {
output[i] = data[i] ^ key[i % keyLen];
}
return output;
}
void printLn(char* toPrint, unsigned long len){
for (unsigned long i = 0; i < len; i++) {
printf("%c", toPrint[i]);
}
printf("\n");
}
int main(){
char *msg = "This is a Message from Boss";
char *key = "nandha";
unsigned long dataLen = strlen(msg);
unsigned long keyLen = strlen(key);
printLn(msg, dataLen);
char* xorMessage = XORCipher(msg, key, dataLen, keyLen);
printLn(xorMessage, dataLen);
xorMessage = XORCipher(xorMessage, key, dataLen, keyLen);
printLn(xorMessage, dataLen);
return 0;
}
Be reminded that xoring can result in null characters in the array that you've allocated, resulting in a terminating character which you might have not intended. To compensate for this, I have added a function to print out based on length since you know this information based on your msg. After xoring twice you should have your original string back, which I my code verified.
My biggest problem is on this line:
for(i=0;i<=strlen(enc);i++) ->
7th line of the function decifrar:
It keeps the loop even with the memset used to clear the memory (it's even bigger than the string length)
Note if I use the actual length of the string in that line the code does works (i.e. replacing strlen(enc) with 60 )
void decipher(int k, char *enc){
char alfa[]="9876543210zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA9876543210zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA";
char *pch;
int i;
for(i=0;i<=strlen(enc);i++){
pch=strchr(alfa, enc[i]);
if (pch) enc[i] = *(pch + k),enc[i]=tolower(enc[i]);
}
printf("%s",enc);
}
int main(){
int keys[6]={1,4,15,24,12,20},i;
char *txt="rfgr r hz grkgb fvzcyrf dhr cergraqr fre grfgnqb ab cebtenzn";
char *txttemp=malloc(sizeof(char)*1024);
for(i=0;i<6;i++){
printf("\n\n\t Attempt number: %d\n\n",i+1);
memset(txttemp,'\0',sizeof(char)*strlen(txt)+30);
memcpy(txttemp, txt, strlen(txt));
decipher(keys[i],txttemp);
}
return 0;
}
What is the point that I am missing? Is the usage of strlen wrong?
It's < not <= in the for-loop.
But as a Note: avoid that pattern. Strlen means you count the length of the string, but you probably should already know it from somewhere (i.e. when you receive it: the file length, the number of charecters returned etc...). Save it and take that value as the length. This is the source of a lot of security holes in programs (a buffer overflow).
std::string has this as a built-in functionality and it's what I would recommend over a plain char* almost all of the time (that is if you can use C++)
I'm coding a program that takes some files as parameters and prints all lines reversed. The problem is that I get unexpected results:
If I apply it to a file containing the following lines
one
two
three
four
I get the expected result, but if the file contains
september
november
december
It returns
rebmetpes
rebmevons
rebmeceds
And I don't understand why it adds a "s" at the end
Here is my code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void reverse(char *word);
int main(int argc, char *argv[], char*envp[]) {
/* No arguments */
if (argc == 1) {
return (0);
}
FILE *fp;
int i;
for (i = 1; i < argc; i++) {
fp = fopen(argv[i],"r"); // read mode
if( fp == NULL )
{
fprintf(stderr, "Error, no file");
}
else
{
char line [2048];
/*read line and reverse it. the function reverse it prints it*/
while ( fgets(line, sizeof line, fp) != NULL )
reverse(line);
}
fclose(fp);
}
return (0);
}
void reverse(char *word)
{
char *aux;
aux = word;
/* Store the length of the word passed as parameter */
int longitud;
longitud = (int) strlen(aux);
/* Allocate memory enough ??? */
char *res = malloc( longitud * sizeof(char) );
int i;
/in this loop i copy the string reversed into a new one
for (i = 0; i < longitud-1; i++)
{
res[i] = word[longitud - 2 - i];
}
fprintf(stdout, "%s\n", res);
free(res);
}
(NOTE: some code has been deleted for clarity but it should compile)
You forget to terminate your string with \0 character. In reversing the string \0 becomes your first character of reversed string. First allocate memory for one more character than you allocated
char *res = malloc( longitud * sizeof(char) + 1);
And the try this
for (i = 0; i < longitud-1; i++)
{
res[i] = word[longitud - 2 - i];
}
res[i] = '\0'; // Terminating string with '\0'
I think I know the problem, and it's a bit of a weird issue.
Strings in C are zero terminated. This means that the string "Hi!" in memory is actually represented as 'H','i','!','\0'. The way strlen etc then know the length of the string is by counting the number of characters, starting from the first character, before the zero terminator. Similarly, when printing a string, fprintf will print all the characters until it hits the zero terminator.
The problem is, your reverse function never bothers to set the zero terminator at the end, which it needs to since you're copying characters into the buffer character by character. This means it runs off the end of your allocated res buffer, and into undefined memory, which just happened to be zero when you hit it (malloc makes no promises of the contents of the buffer you allocate, just that it's big enough). You should get different behaviour on Windows, since I believe that in debug mode, malloc initialises all buffers to 0xcccccccc.
So, what's happening is you copy september, reversed, into res. This works as you see, because it just so happens that there's a zero at the end.
You then free res, then malloc it again. Again, by chance (and because of some smartness in malloc) you get the same buffer back, which already contains "rebmetpes". You then put "november" in, reversed, which is slightly shorter, hence your buffer now contains "rebmevons".
So, the fix? Allocate another character too, this will hold your zero terminator (char *res = malloc( longitud * sizeof(char) + 1);). After you reverse the string, set the zero terminator at the end of the string (res[longitud] = '\0';).
there are two errors there, the first one is that you need one char more allocated (all chars for the string + 1 for the terminator)
char *res = malloc( (longitud+1) * sizeof(char) );
The second one is that you have to terminate the string:
res[longitud]='\0';
You can terminate the string before entering in the loop because you know already the size of the destination string.
Note that using calloc instead of malloc you will not need to terminate the string as the memory gets alreay zero-initialised
Thanks, it solved my problem. I read something about the "\0" in strings but wasn't very clear, which is now after reading all the answers (all are pretty good). Thank you all for the help.
I have a file with integers. I want to write in a buffer those integers as chars (its ascii number). Because it is part of a bigger project please do not post different but please help me on that. What I especially need is chars to be stored in a buffer of type char *.
These are my declarations.
FILE *in;
long io_len = 1000;
char * buffer;
in=fopen("input.txt","a+");
buffer = malloc(io_len * sizeof(*buffer));
if(buffer == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
I am figuring out 2 sollutions.
If I write this one:
read_ret = read(in, buffer, io_len);
it reads from file in, io_len bytes and stores them in buffer. But it reads characters. So for example if I write 123 it will write to buffer 1,2,3 not the character with ascii number 123.
So I did this:
while((fscanf(in,"%d", &i))==1){
printf(": %d\n", i);
}
which reads the integers as I want. Now I am a little bit confused on how I will store them in buffer, as characters. I have tried this but it get me a segmentation fault.
while((fscanf(in,"%d", &i))==1){
printf(": %d\n", i);
buffer=(char) i;
printf("Character in Buffer:%s\n",buffer);
buffer++;
}
Have in mind that later in my file I am writing my buffer somewhere else, so whatever I will do I want the pointer to be at the start of my char array(if it makes sense what I am saying)
Your final code should at least give you a warning about assigning an integer to a pointer in the line buffer=(char) i;. It looks like you want to dereference the pointer.
You are also printing a string when it looks like you really only want to print a character at a time.
Your code should probably look like this:
int character_index = 0;
while((fscanf(in,"%d", &i))==1){
printf(": %d\n", i);
buffer[character_index]=(char) i;
printf("Character in Buffer:%c\n",buffer[character_index]);
character_index++;
}