1

I was doing a caesar cypher in c to practice and I make a functioning one; but it shows a strange behavior. The code is the one follows:

#define lenght 18
char * caesar ( char * cyphertext, int key){
        static char result [lenght];
        for ( int i= 0; i < lenght ; i++){
                result [i] =(char)(((int) cyphertext[i]) + key) % 255;
        }
        return result;
}
int main(){
        char * text = caesar("Hola buenas tardes", 23 );
        printf("%s \n" , text );
        char * check = caesar( text , 256 - 23);
        printf("%s \n" , check);
        return 0;
        }

The encrypted version is _x7y|x7x{|; a shorter number; but when i run the second caesar cypher with the decryption
key it decrypts it with no problem to the original state. I have been looking around and it probably is about how the characters are stored. I will very grateful for any help

Guayguy
  • 21
  • 2
  • 3
    `"Hola buenas tardes"` is 18 characters which means it needs `19` bytes to store because of the NUL terminator. But your `result` array is only `18` bytes. Hence there is undefined behaviour when it's printed with `%s` which requires a string. That may not be the only problem but is a problem. – kaylum Apr 21 '20 at 12:08
  • You may want to use `uint8_t` instead of `char` as a `char` can be [more](https://stackoverflow.com/a/881968/6560579) than 8 bit. Also you should give the length of the array as a argument into the function not as a defined constant – Ackdari Apr 21 '20 at 12:11
  • You also should not use `static` local variable, allocate the correct amount of memory for the result array with [`malloc`](http://man7.org/linux/man-pages/man3/malloc.3.html). – Ackdari Apr 21 '20 at 12:13
  • Although it is true that `char` can be wider than 8 bits, I don't know of any modern system where it actually is wider. Moreover, however wide it is is the correct width for representing characters, *and* on a system where it is wider than 8 bits there will be no type `uint8_t`. So no, I see no reason to prefer `uint8_t`. – John Bollinger Apr 21 '20 at 13:09
  • There are considerations attending using an internal static variable, especially related to multithreading and reentrancy, but there is nothing *inherently* wrong with it, and it offers the distinct advantage of avoiding dynamic allocation to programs, such as the OP's, for which dynamic allocation does not solve any actual problem the program faces. – John Bollinger Apr 21 '20 at 13:12
  • A Unicode character in UTF-16 encoding is between 16 (2 bytes) and 32 bits (4 bytes), though most of the common characters take 16 bits. This is the encoding used by Windows internally – Guayguy Apr 21 '20 at 13:23
  • You might want to take a look at a [ROT47](https://en.wikipedia.org/wiki/ROT13#Variants) implementation for some ideas on how to avoid unprintable characters in the output cyphertext. – rossum Apr 21 '20 at 14:01

2 Answers2

1

The encrypted version is _x7y|x7x{|; a shorter number;

No, what printf prints is the above. Or even more precisely, that's how your terminal displays what printf prints. If you want to be certain exactly what the encrypted version is then you should run your program in a debugger, and use it to examine the bytes of the encoded version.

Your approach will encode some character codes from the printable ASCII range (codes 32 - 126 decimal) as codes outside that range. How your terminal handles those bytes depends on your configuration and environment, but if it expects UTF-8-encoded data then it will trip over invalid code sequences in the output, and if it expects an ISO-8859 encoding then some of the output codes will be interpreted as control characters from the C1 set. There are other possibilities.

Usually, a Caesar-cypher program is careful to map all printable characters to other printable characters, leaving others alone. The typical academic exercise is even more narrowly scoped, asking for a program that maps only the upper- and lowercase Latin letters, preserving case, and leaves all others (punctuation, digits, control characters) alone. This is, accordingly, left as an exercise.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

The printf function should not be used to print the cipher text, it mainly support ascii characters and you have random unprintable characters. Consider converting it to a hexadecimal string.

NadavS
  • 779
  • 3
  • 12