Search code examples
javascriptccode-conversionscramble

Creating a password scrambler


I'm trying to copy a password scrambler from Javascript to C. What it does is take the ASCII character code of the letter, floor it, divide it, and grab a random character out of a given list.

Javascript version:

function getScrambledPassword(pwd) {
    var cipher = ['k', 's', 'z', 'h', 'x', 'b', 'p', 'j', 'v', 'c', 'g', 'f', 'q', 'n', 't', 'm'];
    var result="";
    if (pwd == null)
        pwd = "";
    pwd = encodeURIComponent(pwd);
    //alert("encoded password: " + pwd);
    for(var i=0;i<pwd.length;i++) {
            var cc = pwd.charCodeAt(i);
        result += cipher[Math.floor(cc/16)] + cipher[cc%16];
    }
    //alert("scrambled password: " + result);
    return result;
}

Example of the scrambler being run: https://jsfiddle.net/w5db66va/

What I've done so far:

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

static char *scramblePassword(char *pwd)
{
    char *cipher[] = {
        "k", "s", "z", "h",
        "x", "b", "p", "j",
        "v", "c", "g", "f",
        "q", "n", "t", "m"
    };

    char *result = "";
    for(int i=0; i < strlen(pwd); i++)
    {
        int cc = (int) pwd[i];
        printf("%d", cc);
        result + cipher[floor(cc/16)] + cipher[cc%16];
    }
    return *result;
}

int main(void)
{
    char *test[] = {"test", "testtwo", "testthree"};
    for (int i=0;i < sizeof(test); i++)
    {
        printf("Original: %s", test[i]);
        printf("Scrambled: %s", scramblePassword(test[i]));
    }
}

The issue I'm experiencing is that when I run the c file (after compilation) it will not output anything at all. What am I doing wrong to the point that I cannot get this to run as I'd expect it?


Solution

  • Continuing from the comment, your problems run a bit deeper than you may first think. To begin, you do not want cipher to be an array of strings, you simply want it to be a character array, e.g.:

        char cipher[] = "kszhxbpjvcgfqnm";
    

    Next, you cannot return an array that is declared within the body of a function. The memory for result is destroyed when scramblePassword returns. Your choices are (1) dynamically allocate result in scramblePassword (and free it in main), or (2) declare storage for result in main and pass it as a parameter to scramblePassword. e.g.:

    #define MAX 32
    
    static char *scramblePassword (char *pwd, char *result)
    {
     ...
        return result;
    }
    
    int main(void)
    {
        char result[MAX] = "";
        ...
            printf ("Scrambled: %s\n", scramblePassword (test[i], result));
    

    Finally, your algorithm, if intended to build an array of scrambled characters from cipher will result in choosing indexes beyond the bounds of cipher resulting in undefined behavior. If the intent is to just assign a value to result[x] regardless of whether it is a valid printable ASCII value, then it may be OK. But if the first is your goal, the results of the algorithm must always result in a value that is within the bounds of cipher, e.g. something like:

             result[i] = cipher[((int)floor (cc / 16) + cc % 16) % sizeof cipher];
    

    Putting all those pieces together, and recalling that main is type int and therefore returns a value, you could do something like:

    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    
    #define MAX 32
    
    static char *scramblePassword (char *pwd, char *result)
    {
        char cipher[] = "kszhxbpjvcgfqnm";
        int i;
    
        for (i = 0; i < (int)strlen (pwd); i++)
        {
            int cc = (int) pwd[i];
            // result[i] = cipher[(int)floor (cc / 16)] + cipher[cc % 16];
            result[i] = cipher[((int)floor (cc / 16) + cc % 16) % sizeof cipher];
        }
        result[i] = 0;  /* you MUST nul-terminate to use as a string */
    
        return result;
    }
    
    int main(void)
    {
        char *test[] = {"test", "testtwo", "testthree"};
        char result[MAX] = "";
    
        for (int i = 0; i < (int)(sizeof test/sizeof *test); i++)
        {
            printf ("\nOriginal : %s\n", test[i]);
            printf ("Scrambled: %s\n", scramblePassword (test[i], result));
        }
    
        return 0;
    }
    

    Example Use/Output

    Which would then result in readable output of:

    $ ./bin/pwscramble
    
    Original : test
    Scrambled: ffgf
    
    Original : testtwo
    Scrambled: ffgffmb
    
    Original : testthree
    Scrambled: ffgffmcff
    

    I'll leave it to you to research what that algorithm is actually supposed to do. Let me know if you have further questions.