0

When I compile my program with mingw on windows and gcc on linux, the executable file doesn't give me the same result.

This code is supposed to take a file and encrypt it.

But when I need to add some bytes if the last block is not full or if the file is less than 32 bytes, Linux adds the value "0" like I want but on Windows, it doesn't work.

By the way, the hexdump of each isn't similar.

to execute it : ./encrypt [FileIn] [FileOut] 1 [yourKey] [yourIV]

Put anything you want for Key and IV, they are written inside the code for the test(I just put "1" and "1" to don't get an error)

argv[3] needs to be a "1" to encrypt

I'm testing it using a file with "toto" written inside (put anything you want, but be under 32 char because it's what i'm testing for now).

Key and IV are same inside the code to debug, it's not a mistake.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*FUNCTIONS*/
int encrypt(char* in, char* out, char* key, char* primalIv);
int decrypt(char* in, char* out);
void myprint(char* content, int size);
char* xor(char* data, char* key, int size);
void bitStuffing(char* in, int rem);

/*GLOBAL VARIABLES*/
int errorLevel;
int blockSize = 32; /*Tailles de blocs en octet*/

/*CALL : ./main inFile outFile methode key iv*/
/*FILE STRUC : [datas] [stuffing] [stuffingValue] [iv]*/
int main(int argc, char** argv)
{
    /*Support de l'aide à l'utilisateur*/
    if(argc == 2 && !strcmp(argv[1],"help"))
    {
        printf("\nUsage : ./cied [inFile] [outFile] [methode] [key] [iv]\n\n");
        printf("[inFile]  : Input file to use\n");
        printf("[outFile] : Ouput file to use\n");
        printf("[methode] : Encrypt (1) or decrypt (0)\n");
        printf("[key]     : The key to use\n");
        printf("[iv]      : The initialisation vector.\n");
        printf("            (none for decrypt !)\n");
        return 0;       /*Fermeture gratieuse du programme*/
    }

    /*Support des erreurs d'arguments*/
    if(argc != 5 && argc != 6)
    {
        printf("[ERR] Args error!\n");
        printf("[INF] Enter 'help' to display help\n");
        return 1;
    }
    else if(atoi(argv[3]) == 1 && argc != 6)        /*Nombre d'arguments pour chiffrement*/
    {
        printf("[ERR] Args error : given %d when waiting 5!\n",(argc-1));
        printf("[INF] Enter 'help' to display help\n");
        return 1;
    }
    else if(atoi(argv[3]) == 0 && argc != 5)/*Nombre d'arguments pour dechiffrement*/
    {
        printf("[ERR] Args error : given %d when waiting 4!\n",(argc-1));
        printf("[INF] Enter 'help' to display help\n");
        return 1;
    }


    /***Chiffrement et dechiffremet***/
    if(atoi(argv[3]) == 1)
    {
        errorLevel = encrypt(argv[1], argv[2],"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");/*Chiffrement*/
        if(!errorLevel)
        {   
            printf("[INF] finished\n");
        }
        else
        {
            printf("[ERR] An error as occured.\n");
        }
    }
    else if(atoi(argv[3]) == 0)
    {
        errorLevel = decrypt(argv[1], argv[2]);     /*Dechiffrement*/
        if(!errorLevel)
        {   
            printf("[INF] finished\n");
        }
        else
        {
            printf("[ERR] An error as occured.\n");
        }
    }
    else
    {
        printf("[ERR] Wrong method given!");
        printf("[INF] Enter 'help' to display help\n");
        return 1;
    }
    return 0;
}


/*FONCTIONS CORE*/
int encrypt(char* in, char* out, char* key, char* primalIv)
{
    /*Variables*/
    char* block = NULL;
    char* xored = NULL;
    char* iv = NULL;
    int readed;
    int inFileSize;
    int numOfBlock;
    int rem = 0;
    int i;
    FILE *inFile;
    FILE *outFile;

    iv = primalIv;

    /*Ouverture des fichiers*/
    inFile = fopen(in,"rb");
    outFile = fopen(out,"w");

    /*Gestion des erreurs de fichier*/
    if(inFile == NULL)
    {
        printf("[ERR] Problem reading input file. Please check path and permissions.\n");
    }
    else if(outFile == NULL)
    {
        printf("[ERR] Problem reading output file. Please check path and permissions.\n");
    }

    block = malloc(blockSize);

    /*Récupération de la longueur du fichier*/
    fseek(inFile, 0, SEEK_END);
    inFileSize = ftell(inFile);
    rewind(inFile);

    /*Calcul du nombre de bloc et du reste*/
    numOfBlock = inFileSize / blockSize;
    rem = inFileSize % blockSize;
    printf("[INF] File will be split in %d block(s). %d will remain.\n",numOfBlock,rem);
    if(inFileSize < blockSize)
    {
        readed = fread(block,1,blockSize,inFile);
        printf("[INF] readed %d bytes \n",readed);
        /*Bourrage*/
        bitStuffing(block,(blockSize-readed));
        /*Xor avec l'IV*/
        xored = xor(block,iv,blockSize);
        /*Xor avec la clé*/
        xored = xor(xored,key,blockSize);
        /*Sauvegarde du block pour réutilisation en tant qu'IV*/
        iv = xored;
        /*Ecriture dans le fichier*/
        fwrite(xored,1,blockSize,outFile);
    }
    else
    {
        for(i=0;i<numOfBlock;i++)
        {
            printf("qzekonfk le\n");
            readed = fread(block,1,blockSize,inFile); 
            printf("[INF] readed %d bytes \n",readed);
            if(readed != blockSize)
            {
                printf("[WRN] The readed block siez is different than usual !(%d != %d)\n",blockSize,readed);
            }
            /*Xor avec l'IV*/
            printf("IV :\n");
            xored = xor(block,iv,readed);
            /*Xor avec la clé*/
            printf("KEY :\n");
            xored = xor(xored,key,readed);
            /*Sauvegarde du block pour réutilisation en tant qu'IV*/
            iv = xored;
            /*Ecriture dans le fichier*/
            fwrite(xored,1,readed,outFile);
        }
        /*Bourrage*/
        if(rem)
        {
            readed = fread(block,1,blockSize,inFile);
            printf("[INF] readed %d bytes \n",readed);
            /*Bourrage*/
            bitStuffing(block,(blockSize-readed));
            /*Xor avec l'IV*/
            xored = xor(block,iv,readed);
            /*Xor avec la clé*/
            xored = xor(xored,key,readed);
            /*Sauvegarde du block pour réutilisation en tant qu'IV*/
            iv = xored;
            /*Ecriture dans le fichier*/
            fwrite(xored,1,readed,outFile);
        }
    }

    /*Inscription de rem dans le fichier pour préparer le déchiffrement*/
    fprintf(outFile, "%c",rem);

    /*Inscription de l'IV*/
    printf("IV (again):\n");
    fwrite(xor(primalIv,key,blockSize),1,blockSize,outFile);

    /*Free des malloc*/
    free(block);
    free(xored);

    return 0;
}

int decrypt(char* in, char* out)
{

    return 0;
}

/*FONCTIONS UTILITAIRES*/
char* xor(char* data, char* key, int size)
{
    int i;
    char* result = malloc(size);
    for(i=0; i<size; i++)
    {
        result[i] = data[i] ^ key[i];
        printf("  %x ^ %x = %x\n",data[i],key[i],result[i]);
    }
    return result;
}

void myprint(char* content, int size)
{
    int i;
    printf("  ");
    for(i=0;i<=blockSize;i++)
    {
        printf(" %x",content[i]);
    }
    printf("\n");
}

void bitStuffing(char* in, int rem) {
    int i;
    printf("\nBEGIN STUFFING");
    for(i=rem; i<sizeBlock; i++) {
        in[i] = 0;
        /*printf("%x", in[i]);*/
    }
    printf("\nEND STUFFING\n");
}
Swifty
  • 839
  • 2
  • 15
  • 40
papi singe
  • 31
  • 4
  • 3
    Without looking to much into your code (there's a lot), there is one things I noticed in `encrypt`: you open `inFile` with mode `"rb"`, but `outFile` with mode `"w"` without the "b". In Windows you need that "b" specially if the file has binary stuff (i.e. non-ascii chars). Change the call to `fopen(out,"wb");` and see what happens next. – Pablo Jan 04 '18 at 00:48
  • If a program behaves different with different compilers it's a sign of undefined behavior. Furthermore, this is really a lot of code. Create a [mcve] – klutt Jan 04 '18 at 00:48
  • Aside: you don't call `myprint` but `for(i=0;i<=blockSize;i++)` is probably over range by 1. – Weather Vane Jan 04 '18 at 01:12
  • 1
    Does not compile. `error: use of undeclared identifier 'sizeBlock'` (guess: must be `blockSize`). `xored` is assigned a `malloc`ed value multiple times but only freed once. Input is opened explicitly as binary (`"rb"`), output as 'regular' (`"w"`). That may be the issue: "If t or b is not given in mode, the default translation mode is defined by the global variable _fmode." (https://msdn.microsoft.com/en-us/library/yeby3zcb.aspx) – Jongware Jan 04 '18 at 01:49
  • Copy/paste only the code that you tested. – Martin James Jan 04 '18 at 02:00
  • 1
    We see much worse Qs every day here, at least you posted some code (too much), but you will learn, right? so Pluse-uno from me, but Please read https://stackoverflow.com/help/on-topic , https://stackoverflow.com/help/how-to-ask , https://stackoverflow.com/help/dont-ask , https://stackoverflow.com/help/mcve and take the [tour](https://stackoverflow.com/tour) before posting more Qs here. Good luck. – shellter Jan 04 '18 at 03:22
  • This `bitStuffing(block,(blockSize-readed));` looks wrong. Just imagine an input file size of 1. – alk Jan 04 '18 at 09:09
  • You're true, i found it juste before read your post – papi singe Jan 04 '18 at 10:42
  • what happens when the number of arguments (argc) is 3 or 4 or 7? What happens if the number of arguments is 2 but the argument is not `help`? in the `Usage` statement, much better to use `%s` and add the parameter: `argv[0]`. What happens when argv[3] is not 0 or 1? – user3629249 Jan 05 '18 at 01:46
  • When calling `fopen()`, immediately check that the returned value is NOT NULL and if it is NULL, then immediately call `perror()` so the reason the system thinks the function failed is also output to `stderr`. Error message should be output to `stderr`, not `stdout`, so these kinds of statements: `printf("[ERR] Problem reading input file. Please check path and permissions.\n");` are outputting the error message to the wrong place. – user3629249 Jan 05 '18 at 01:53
  • the posted code contains a number of unused parameters. if your going to keep those parameters, then the first statement in the body of the function should be: `(void)parametername;` – user3629249 Jan 05 '18 at 01:54
  • when compiling, always enable the warnings, then fix those warnings. ( for `gcc`, at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ). Amongst lots of implicit conversions, there is also a variable named: `sizeBlock` that is not defined anywhere in the posted code. – user3629249 Jan 05 '18 at 01:56

1 Answers1

1

@alk You're true, i found it just before reading your post. My friend give a wrong value to the bitStuffing() function. He don't need to give the number of empty bytes, but the byte where the loop have to begin. Then it will be

bitStuffing(block, readed);

and not

bitStuffing(block, (blockSize-readed));

For everyone who want a little less code, i create this to have essentially the stuffing :

#include <stdio.h>
#include <stdlib.h>

void bitStuffing(char* in, int rem);
void myprint(char* content, int size);
int blockSize = 32;

int main()
{
    char* block;
    int inFileSize = 4; /*In my example, the file used is a text file containing "toto"*/
    int readed;
    FILE *outFile;
    readed = inFileSize % blockSize; /*Getting the number of bits to stuff*/
    block  = malloc(blockSize);
    block[0] = "t";
    block[1] = "o";
    block[2] = "t";
    block[3] = "o";
    bitStuffing(block, readed);
    outFile  = fopen("C:/Users/Julien/Desktop/text3.txt", "wb");
    fwrite(block,1,blockSize,outFile);
    fclose(outFile);
    return 0;
}


void bitStuffing(char* in, int begin) {
    printf("\nBEGIN STUFFING");
    printf("\nrem =%2d", begin);
    int i;
    for(i=begin; i<blockSize; i++) {
        in[i] = 0;
        printf("\ni =%1d | value =%1x\n     ",i, in[i]);
        myprint(in, i);
    }
    printf("\nEND STUFFING\n");
}


void myprint(char* content, int size)
{
    int i;
    printf("\n");
    for(i=0;i<size;i++)
    {
        printf("%2x",content[i]);
    }
    printf("\n");
}

This works as well like i want. Then i was sure that the problem didn't come from the bitStuffing

Thank's everybody

Now, i will slap my friend

papi singe
  • 31
  • 4
  • Correct me if i'm wrong. I think it works on linux because the memory is already set with the NULL value. So, when i display the result, it seems work. But on Windows, the memory already have something written inside. So the bitStuffing function complete the difference between (sizeBlock-readed) and sizeBlock, but bytes who stay betwen readed and (sizeBlock-readed) aren't modified. That's why the outFile contain something like that : "HOMEPATH=\Users\Jul", datas in memory but not changed by the function. – papi singe Jan 04 '18 at 13:18
  • @alk i have tryed but i can't before tomorow. I think now that the topic title is wrong, but i don't know how i can turn it to be understandable. Is it modifiable or not ? And by what can i replace it ? – papi singe Jan 04 '18 at 13:22