-1

I'm trying to convert 2 functions from C to Javascript, but I'm failing on that.

The C functions im trying to convert is:

void encrypt(char password[],int key)
{
    unsigned int i;
    for(i=0;i<strlen(password);++i)
    {
        password[i] = password[i] - key;
    }
}

void decrypt(char password[],int key)
{
    unsigned int i;
    for(i=0;i<strlen(password);++i)
    {
        password[i] = password[i] + key;
    }
}

The C functions is from: http://c-program-example.com/2012/04/c-program-to-encrypt-and-decrypt-a-password.html

What i did in Javascript is this:

var password = "hello"

var key = 322424;

   for (var i=0; i<password.length; i++) {

        var char = password[i].charCodeAt();


        var s = String.fromCharCode(char-key);


        alert(s);

     }  

I'm putting the alert to see if it working correctly before making them as functions. Can someone please show me how it is done correctly in Js?

John
  • 51
  • 1
  • 8
  • 3
    Use `charCodeAt(i)` – Luca Kiebel Sep 12 '18 at 13:26
  • I'm quite new into javascript, could you please provide a working sample – John Sep 12 '18 at 13:27
  • changing password[i].charCodeAt(); into password.charCodeAt(i) made it output chinese characters... it dont output the same as the C functions – John Sep 12 '18 at 13:29
  • 1
    Tip: `encrypt` is the same as `decrypt` with `-key`. – Eugene Sh. Sep 12 '18 at 13:29
  • 1
    javascript doesn't have the same concept of types as C, so when you subtract 322424 from `char`, you're going to get a very negative number – Chris Turner Sep 12 '18 at 13:31
  • Chris Turner how can i make it like C? can you please show me – John Sep 12 '18 at 13:32
  • Can you provide examples of inputs and their expected output of the functions? – Alvaro Castro Sep 12 '18 at 13:35
  • It's unclear if you understand exactly what that C function does (passing a null-terminated array of char of unknown length, integer promotion from char to int to perform the addition and then truncation and cast to a char). – Bob__ Sep 12 '18 at 13:47
  • The C functions works, i just wanted to understand how to make the same function in Js... hoped someone could show me so i can understand – John Sep 12 '18 at 13:49
  • 1
    Re. "how can i make it like C?" ; after each arithmetic operation, mask out the upper bits so the result is modulo-256 (e.g. `(char - key) & 0xff`). I cannot post an answer because I am no JavaScript expert, and that is by no means the only issue. – Clifford Sep 12 '18 at 14:10
  • @AlvaroCastro Well, it's even worse, C [doesn't really mandate any particular encoding](https://stackoverflow.com/a/3996106/4944425). Consider that `char` could be signed in many implementations: https://wandbox.org/permlink/boPD4K5aSQ9ImGX3 – Bob__ Sep 12 '18 at 14:10
  • You probably need to use _typed arrays_ (using `Int8` type) in order to create an equivalent - especially if the encryption/decryption need to be inter-operable (e.g. encrypted in C and decrypted in JS). – Clifford Sep 12 '18 at 14:16

2 Answers2

0

A char in C is actually a tiny integer, which value in hexa goes from 00 to FF. char is signed in many implementations (unsigned char is not), so its values go from -128 to 127 (256 values total, or 0 to 255 if unsigned). An array of chars, char[] is an array of tiny integers, conventionally the last char of a 'string' in C is the byte 0x00 that marks the end (for instance, printf knows the end is there when the byte 0 is met).

In Javascript a string is a set of Unicode characters.

In C,

char s[] = "hello";
int k = 322424;
char *t = s;
while(*t) *t++ -= k; // 't' is the encoded version of 's'
// print the integer values of the new encoded 'string'
for(t=s ; *t ; t++) printf("%d ", *t); // -16 -19 -12 -12 -9
// (unsigned: 240 237 244 244 247, or add 256 to negative values above)
printf("\n");

A char cannot contain more than a byte.

In Javascript, you have to keep the resulting number in a byte-range, otherwise, a multi-byte character might be stored instead. For instance

String.fromCharCode(0x3042)  gives "あ" (Unicode [character 0x3042](https://www.key-shortcut.com/en/writing-systems/%E3%81%B2%E3%82%89%E3%81%8C%E3%81%AA-japanese/))

In C,

char c = 0x3042; // will only keep one byte, the LSB, 0x42

Thus in Javascript, try something like

var s = "hello";
var k = 322424;
var i,l = s.length;
var t = '';
// Note the `& 0xff` that keep the result within a byte range
for(i=0 ; i<l ; i++) t += String.fromCharCode((s.charCodeAt(i) - k) & 0xff);
// 't' is the result, let see its char codes
var u = '';
for(i=0 ; i<l ; i++) u += t.charCodeAt(i) + ' ';

console.log(u);  // 240 237 244 244 247 (same as in C, 240-256 = -16 ...)

The JS char codes are unsigned, thus the positive results. They're the same as in C.

Déjà vu
  • 28,223
  • 6
  • 72
  • 100
  • Whether `char` is sugned or unsigned in C is implementation defined. Adding 256 to a char value -16 in C will only result in 240, if assigned to a larger type - when assigned to a `char` the will remain -16. It has no effect on the bit pattern. Simpler to use explicit `unsigned char` or cast to `unsigned char` - but it makes no difference to the character the code is associated with; -16 and 240 refer to the same `char` bit pattern on platforms where `char` is 8 bit (again implementation defined), and therefore the same character. – Clifford Sep 12 '18 at 14:26
  • @Clifford `char` signedness is implementation dependent, had to be said (and was added). Besides, I don't think the answer was missing the rest, did it? – Déjà vu Sep 12 '18 at 14:48
  • `char c = 0x3042; // will only keep one byte, the LSB, 0x42` Actually the C standard says the result is either an implementation defined value or an implementation defined signal, so in principle this could segfault (raise SIGSEGV). – melpomene Sep 12 '18 at 17:20
0

Try this, as said by Clifford in the comments, each char code has to be masked to modulo-256 because the size of char. Also, since decrypt is the same but substracting key, I reused encrypt but with a negative key.

Here you have a working snippet, let me know if it gives the desired output.

function encrypt (password, key) {
    var i,
        output = '';

    for (i = 0; i < password.length; i++) {
        var charCode = password.charCodeAt(i),
            keyedCharCode = (charCode - key) & 0xff;

        output += String.fromCharCode(keyedCharCode);
    }

    return output;
}

function decrypt (password, key) {
    return encrypt(password, -key);
}

var password = 'hello',
    key = 322424,
    encrypted = encrypt(password, key),
    decrypted = decrypt(encrypted, key);

console.log('encrypt', encrypted);
console.log('decrypt', decrypted);
Alvaro Castro
  • 811
  • 1
  • 9
  • 26
  • Glad it worked. Just as a an advice if you come here again with another transpilation question, provide examples of inputs and its expected output along with the code, that way we have something to test with when answering. There are a lot of differences between JS and C, not just syntax, that can be easily overlook. – Alvaro Castro Sep 12 '18 at 19:01