1

I am trying to build a program that encrypts a password and then does the reverse process (tells a correct password from an encrypted one).

For that, I have:

  • a password (char[] type);

  • an encryption key (vector - int[] type) that has the same length as the char of the password;

  • two steps (placed also in a vector of type int step[2]).

The requirement is that the encryption process has to be built using these two steps:

  • the first one (the value in step[0]) is used to add the value (ASCII) starting from the first position of the password char to the first position of the encryption key vector for a number of steps equal to the first step step[0];

for example, adds char password[0] to int key[0], then adds char password[1] to int key[1] and so on for a number of steps equal to the value placed in step[0].

  • the second one (step[1]) subtracts from the corresponding position of the ASCII value of the password char, the value of the encryption key for a number of steps equal to the second step (step[1]).

for example, subtracts char password[5] from int key[5], then subtracts char password[6] from int key[6] and so on for a number of steps equal to the value placed in step[1].

And then, the process repeats until the end of the length of the password char.

I built a function as below that should do this (addition for a number of steps, then subtraction for a number of other steps, and repetition of the process until the end of the password char - the encryption key vector has the same length as the password char).

The result is placed in a new vector (for encryption) or in a new char (for the reverse process of finding the password).

void criptareFinal(char password4[255], 
                   int longKey1[255], 
                   int b4, 
                   int step2[2]) {
    int encryptedPass[255];
    int a = step2[0], 
        b = step2[1], 
        n = b4, 
        i,
        ap = a, 
        bp = b; 

    for (i = 0; i < n; i++) {
        if (ap > 0) {
            encryptedPass[i] = longKey1[i] + password4[i];
            ap--;
        }
        else if (bp > 0) {
            encryptedPass[i] = longKey1[i] - password4[i];
            bp--;
        }
        else if (ap == 0 && bp == 0) {
            ap = a;
            bp = b;
        }
    }

    int i1;
    printf("\n");
    for (i1 = 0; i1 < b4; i1++)
        printf("%d ", encryptedPass[i1]);
}

Then if I try to printf the vector (for encryption process) in order to show the content of the vector, a message similar to this one appears:

1090 923 916 1151 942 913 962 998 960 936 962 917 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460

why does it show "-858993460"?


Also, if a try to printf the char for showing the password in the reverse process (form an encrypted password to a readable one) using the following code,

void decriptareFinal(int encryptedPass5[255], 
                     int longKey2[255], 
                     int b5, 
                     int steps3[2]) {   
    char Password1[255];
    int a = steps3[0], 
        b = steps3[1], 
        n = b5, 
        i2, 
        ap = a, 
        bp = b;

    for (i2 = 0; i2 < n; i2++) {
        if (ap > 0) {
            Password1[i2] = encryptedPass5[i2] - longKey2[i2];
            ap--;
        }
        else if (bp > 0) {
            Password1[i2] = longKey2[i2] - encryptedPass5[i2];
            bp--;
        }
        else if (ap == 0 && bp == 0) {
            ap = a;
            bp = b;
        }
    }

    int j2;
    printf("\n");
    for (j2 = 0; j2 < b5; j2++)
        printf("%c", Password1[j2]);
}

then this message appears:

côő~ypaXOF╠╠╠╠╠╠╠╠

what is "╠"?

this "╠╠╠╠╠╠╠╠" is an incorrect display (the rest "côő~ypaXOF" is correct).


Also. I tried to add and subtract manually form [0] to the end of the string/vector and if I do that, no error message of type -858993460 or of type ╠╠╠╠╠╠╠╠ appears. It works fine and that tells me that the values in the char (password) or int (key) are correct.

If it is of importance, I work on Windows 64bit, but I use Visual Studio. Also, I have a Mac. There I have the same problem, but instead of -858993460 or ╠╠╠╠╠╠╠╠ I get other messages (for instance 0 instead of -858993460).

Student
  • 805
  • 1
  • 8
  • 11
  • 2
    Wow. Can you please reduce the whole thing to few sentences of the problem description and to the [mcve]? – Eugene Sh. Aug 09 '18 at 15:48
  • While this question has lots of detail, perhaps it has way too much for what should be a simple query. It sounds like you need to step through this code in a debugger to find out where it went wrong, as well as write more focused unit tests to verify specific functions as working correctly before depending on those calculations in later parts of your code. – tadman Aug 09 '18 at 15:48
  • 1
    These characters come from [code page 437](https://en.wikipedia.org/wiki/Code_page_437) or classic DOS characters. Are you running this compiler in that sort of environment? – tadman Aug 09 '18 at 15:50
  • Another note: C tends to pass around `char* x` and not `char x[255]`. Note the first form is a pointer to a buffer of unknown length, meaning it's flexible and can be used on arbitrary length buffers. The second passes in a *copy* of a specific length array which limits how it can be used. – tadman Aug 09 '18 at 15:51
  • 6
    -858993460 is a magic number when you write C++ code with Visual Studio. 0xcccccccc, it tells you that you are using an uninitialized variable. Same for the string, also 0xcc in code page 437. Using an uninitialized variable is always a bug, their wonky value helps you locate the bug. – Hans Passant Aug 09 '18 at 15:54
  • 1
    where are b6 and b7 defined? – JGroven Aug 09 '18 at 16:02
  • `int a = steps 3[0]` is invalid, `j` is defined twice, `b7` is not defined. I'm surprised it compiled (it didn't for me). Note that on a parameter line an array is not passed by size, with `int longKey2[255]` the 255 is ignored and is exactly the same as `int longKey2[]` or `int * longKey2`. – cdarke Aug 09 '18 at 16:11
  • 1
    @tadman: in a parameter list, `char x[255]` does not pass a copy of a specific length character array, it passes a pointer, just like `char * x`. The 255 is ignored and is mis-leading. Lengths are used for multi-dimensional arrays, but the first size is always ignored, e.g. `char x[][42]` is fine. – cdarke Aug 09 '18 at 16:17
  • Further to Hans' comment, the value 0xcc is usually an indicator that you are reading an uninitialized _stack variable_ (or "local variable"). – Tim Randall Aug 09 '18 at 16:26
  • where are b6 and b7 defined? @JGroven ; it is an typing error of mine. these two are defined, but I took them from another function (where they are defined) and I did not make the correction when posting. For the functions posted above, they shoud be read as b4 and b5. – claudiu dragusin Aug 09 '18 at 16:39
  • @cdarke - j and b6 and b7 are fine. I took them from another function and I did not make the necessary corrrections. int a = step3 [0] is also an error of typing. The program compiled, there were no errors except those pointed by me above. Thank you for the comments. – claudiu dragusin Aug 09 '18 at 16:48
  • -858993460 = 0xCCCCCCCC and ╠ is 0xCC in codepage 437 which means [you've accessed uninitialized memory](https://stackoverflow.com/q/370195/995714) You can find tons of questions about ╠ and 0xCC here on SO – phuclv Aug 18 '18 at 11:09

3 Answers3

0

There were a lot of changes I made to your code. Here is the list:

  • Added more #include tags for standard libraries (I'm guessing you already had some and didn't post them)
  • Changed function arguments to be char* instead of char[], it is not conventional to use char arrays in function arguments and I'm not even sure how they work in your code.
  • Got rid of uneccessary/extra variables: ap, bp and some others. Since C is pass-by-value, you don't need temporary variables for the steps variables.
  • Fixed variable naming. A lot of your variable names were unintuitive/weird and I felt I had to change the names to something more accurate.
  • Used malloc (dynamic memory allocation) instead of placing char arrays on the stack. This is more flexible and reduces the chances of those gotchas, but does open up more possibility for segfaults.
  • Fixed your encryption/decryption algorithm since it would leave the char the same if it had just finished going through both steps (ap == 0 && bp == 0).
  • Fixed some syntax errors.
  • Added some debugging fprintf statements, so you can see what's going on.

As for your weird ╠ character, I can't see why your code would print that other than maybe you have some memory error or your environment is switching between Unicode and ASCII or something. Frankly, I don't want to figure it out because your code is kind of a mess and I don't think you posted all of it because it had compilation errors when I first ran it.

I also added some null terminating characters ('\0') to the ends of the malloc'd strings that will be handy for properly printing the strings when debugging.


Anyway, enough of that. Here's the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char *criptareFinal(char *plaintext, int *key, int len, int *steps) {
    char *ciphertext = malloc(len + 1);
    int a = steps[0], b = steps[1], n = len;

    for (int i = 0; i < n; i++) {
        if (a == 0 && b == 0) {
            a = steps[0];
            b = steps[1];
        }

        if (a > 0) {
            ciphertext[i] = key[i] + plaintext[i];
            a--;
        }
        else if (b > 0) {
            ciphertext[i] = key[i] - plaintext[i];
            b--;
        }
    }

    ciphertext[len] = '\0';

    fprintf(stderr, "\n");
    fprintf(stderr, "ENCRYPTION: ");
    for (int i = 0; i < n; i++)
        fprintf(stderr, "%d ", ciphertext[i]);

    return ciphertext;
}

char *decriptareFinal(char *ciphertext, int *key, int len, int *steps) {   
    char *plaintext = malloc(len + 1);
    int a = steps[0], b = steps[1], n = len;

    for (int i = 0; i < n; i++) {
        if (a == 0 && b == 0) {
            a = steps[0];
            b = steps[1];
        }

        if (a > 0) {
            plaintext[i] = ciphertext[i] - key[i];
            a--;
        }
        else if (b > 0) {
            plaintext[i] = key[i] - ciphertext[i];
            b--;
        }
    }

    plaintext[len] = '\0';

    fprintf(stderr, "\n");
    fprintf(stderr, "DECRYPTION: ");
    for (int i = 0; i < n; i++)
        fprintf(stderr, "%d ", plaintext[i]);

    return plaintext;
}

int main() {
    char *toEncrypt = "Hello World!";
    int steps[] = {2, 3};
    int key[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};

    int len = strlen(toEncrypt);

    fprintf(stderr, "INITIAL: ");
    for (int i = 0; i < len; i++)
        fprintf(stderr, "%d ", toEncrypt[i]);

    fprintf(stderr, "\n");
    char *encrypted = criptareFinal(toEncrypt, key, len, steps);
    fprintf(stderr, "\n");
    fprintf(stderr, "ENCRYPTED: %s\n", encrypted);
    char *decrypted = decriptareFinal(encrypted, key, len, steps);
    fprintf(stderr, "\n");
    fprintf(stderr, "DECRYPTED: %s\n", decrypted);

}

NOTE: There is no error handling in this code, so if the user inputs are invalid in pretty much any way, the code will break and could lead to segfaults, infinite loops, etc. You should add error handling to every char* manipulation and array iteration before you use this in a properly-made application.


And some sample output:
INITIAL: 72 101 108 108 111 32 87 111 114 108 100 33

ENCRYPTION: 73 103 -105 -104 -106 38 94 -103 -105 -98 111 45
ENCRYPTED: Igùÿû&^Öù₧o-

DECRYPTION: 72 101 108 108 111 32 87 111 114 108 100 33
DECRYPTED: Hello World!

Let me know if you have any questions.

agillgilla
  • 859
  • 1
  • 7
  • 22
  • `sizeof(char)` is 1 by definition so there is no need to multiply by it. – Arkku Aug 09 '18 at 16:52
  • @Arkku OK thanks I fixed the `sizeof(char)` references. – agillgilla Aug 09 '18 at 16:54
  • Also note that you allocate `len` space but later assign to `plaintext[len]`, which requires `len + 1` space (because 0 is the first index). – Arkku Aug 09 '18 at 16:55
  • @ agillgilla; Thank you. I shall try it. I am familiar (a little with the modifications you made), but being a beginner, I have to stick to the functions displayed in my examples above, since my educational process (in the school I follow) did not go so far to cover the functions you use. I shall try it and let you know. Thanks also for the comments. – claudiu dragusin Aug 09 '18 at 16:56
  • This also _looks_ like it not all paths through the loop assign anything to the result array, i.e., the risk of uninitialized data still remains if this is so. However, in practice I think this might never happen, in which case the `else if (b > 0)` should be just `else` without a condition. (edit: Ok, well, because the first condition is `a == 0 && b == 0`, you can't let `b` go negative or that will never match. So either there needs to be `a == 0` and `b == 0` as separate `if`s, or as `a == 0 || b == 0`, or something else is broken.) – Arkku Aug 09 '18 at 17:00
  • All code paths will initialize the array unless `steps` contains a 0. I should edit my post though and clearly say that there is virtually no error handling in this code and invalid user inputs can break it very easily. – agillgilla Aug 09 '18 at 17:06
0

In the first function, you iterate i from 0 to n one step at a time. However, not all paths through the loop body assign anything to encryptedPass[i] - this is the case for both the last else if and when none of the if conditions matches. Likewise for the second function, but for Password1[i].

At the end of each of these functions you do, however, unconditionally print all values from these arrays, which means they are uninitialized values. (And you iterate up to unknown values b6 and b7, whereas you probably should iterate up to the same n that you use in the first loop.)

To fix, either ensure that each iteration writes something to the index, or have a separate write position index or pointer and only advance it when you write something.

Arkku
  • 41,011
  • 10
  • 62
  • 84
  • That I thought of. It felt somthing wrong when finishing the lenght of the sum of the two steps. Thanks, I shall try to use your observations. – claudiu dragusin Aug 09 '18 at 16:59
0

Thank you all for the answers, esspecially to Arkku. That helped a lot. I fixed it and now it works fine. I added "i = i - 1" at the last condition, after "else if (ap == 0 && bp == 0)" in order to mantain the iteration on the same position.

This is what I did:

for (i2 = 0; i2 < n; i2++) {
if (ap > 0) {
    Password1[i2] = encryptedPass5[i2] - longKey2[i2];
    ap--;
}
else if (bp > 0) {
    Password1[i2] = longKey2[i2] - encryptedPass5[i2];
    bp--;
}
else if (ap == 0 && bp == 0) {
    ap = a;
    bp = b;
    i = i - 1;
}

That solved the problem.

Same at the other function:

for (i = 0; i < n; i++) {
if (ap > 0) {
    encryptedPass[i] = longKey1[i] + password4[i];
    ap--;
}
else if (bp > 0) {
    encryptedPass[i] = longKey1[i] - password4[i];
    bp--;
}
else if (ap == 0 && bp == 0) {
    ap = a;
    bp = b;
    i = i - 1;
}

No more "-858993460" when I encrypt and no more "╠╠╠╠╠╠╠╠" when I printf the password in the reverse process.

Thank you all again, and sorry for the lenght of the original message. Next time I shall take that into account.

cd