Thread: xor encryption / weird results on decryption

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    808

    xor encryption / weird results on decryption

    i have written a simple encrypt / decrypt program.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void EncryptString(char phrase[], char encrypted_phrase[], char key[], int lenPhrase, int lenKey);
    void DecryptString(char encrypted[], char result[], char key[], int lenEncrypted, int lenKey);
    
    int main()
    {
        char phrase[] = "The quick brown fox jumps over the lazy dog", encrypt[] = "HELLO", encrypted_phrase[100], result[100];
    
        EncryptString(phrase, encrypted_phrase, encrypt, strlen(phrase), strlen(encrypt));
        printf("%s \n%s \n", phrase, encrypted_phrase);
    
        DecryptString(encrypted_phrase, result, encrypt, strlen(encrypted_phrase), strlen(encrypt));
        printf("%s \n%s \n", encrypted_phrase, result);
    
        return 0;
    }
    
    void EncryptString(char phrase[], char encrypted_phrase[], char key[], int lenPhrase, int lenKey)
    {
        int i, j = 0;
    
        for (i = 0; i < lenPhrase; i++) //cycle through the array encrypting 1 character at a time
        {
            if (j == lenKey) //if j equals the length of the string key reset to 0
            {
                j = 0;
            }
            encrypted_phrase[i] = phrase[i] ^ key[j]; //xor the current character of the phrase with the current key character
            j++;
        }
    }
    
    void DecryptString(char encrypted[], char result[], char key[], int lenEncrypted, int lenKey)
    {
        int i, j = 0;
    
        for (i = 0; i < lenEncrypted; i++)
        {
            if (j == lenKey)
            {
                j = 0;
            }
            result[i] = encrypted[i] ^ key[j];
            j++;
        }
    }
    on decrypt it insists on adding an extra 3 characters to the end. they are completely random as to what they are.

    i have stepped through the code and made sure im not over addressing any of the arrays and the only "error" i could find is that the length of the string gains three charaters between finishing the encrypting function and the decryption function starting.

    coop

  2. #2
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Some things for you to think about:

    1- What happens if your "plaintext" is "OOOOOOOOOOOOOOO" and your key is "HELLO"? What will be printed?
    2- You do remember that strings, in C, end with a NUL char, didn't you?
    3- The result of a XOR will give you a printable character?

    Here's a modified code from yours:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    void EncryptString( char phrase[], char encrypted_phrase[], char key[], int lenPhrase, int lenKey );
    void DecryptString( char encrypted[], char result[], char key[], int lenEncrypted, int lenKey );
    
    void printblock( char *, char *, size_t );
    
    int main( void )
    {
      char phrase[] = "The quick brown fox jumps over the lazy dog", encrypt[] = "HELLO"; 
    
      // FIX: Notice we need to inicialize these arrays!
      char encrypted_phrase[100] = "", result[100] = "";
    
      printblock( "phrase[]", phrase, strlen( phrase ) + 1 );
    
      EncryptString( phrase, encrypted_phrase, encrypt, strlen( phrase ), strlen( encrypt ) );
      printblock( "encrypted_phrase[]", encrypted_phrase, strlen( phrase ) + 1 );
    
      DecryptString( encrypted_phrase, result, encrypt, strlen( encrypted_phrase ), strlen( encrypt ) );
      printblock( "result[]", result, strlen( phrase ) + 1 );
    
      return 0;
    }
    
    void EncryptString( char phrase[], char encrypted_phrase[], char key[], int lenPhrase, int lenKey )
    {
      int i, j = 0;
    
      for ( i = 0; i < lenPhrase; i++ ) //cycle through the array encrypting 1 character at a time
      {
        if ( j == lenKey ) //if j equals the length of the string key reset to 0
          j = 0;
    
        encrypted_phrase[i] = phrase[i] ^ key[j]; //xor the current character of the phrase with the current key character
        j++;
      }
    
      // FIXME: Should put an '\0' at the end...
      //        This won't help much 'cause ANY char in the string can be '\0' after
      //        XOR... :(
    }
    
    void DecryptString( char encrypted[], char result[], char key[], int lenEncrypted, int lenKey )
    {
      int i, j = 0;
    
      for ( i = 0; i < lenEncrypted; i++ )
      {
        if ( j == lenKey )
          j = 0;
    
        result[i] = encrypted[i] ^ key[j];
        j++;
      }
    
      // FIXME: Should put an '\0' at the end...
      //        Assuming the result is a string...
    }
    
    void printblock( char *prompt, char *p, size_t size )
    {
      size_t offset = 0;
      char *oldp;
    
      oldp = p;
      printf( "%s:\n%08zx:", prompt, offset );
      while ( size-- )
      {
        printf( " %02x", *p );
    
        p++;
        offset++;
        if (p - oldp > 15)
        {
          oldp = p;
          printf("\n%08zx:", offset);
        }
      }
      puts("\n");
    }
    Last edited by flp1969; 06-20-2019 at 07:25 AM.

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    A better implementation (I think):
    Code:
    #include <stdio.h>
    #include <string.h>
    
    static void printblock( char *, char *, size_t );
    static void encrypt( char *, char *, char *, size_t, size_t );
    #define decrypt(p,e,k,ts,ks) encrypt( (p), (e), (k), (ts), (ks) )
    
    int main( void )
    {
      size_t size, ksize;
      static char msg[] = "Hello, world! I am a plain text!";
      static char key[] = "HELLO";
    
      // FIXME: Could be dynamically allocated...
      char enc[100], dec[100];
    
      size = strlen( msg );
      ksize = strlen( key );
    
      printf( "Plain text: \"%s\".\n\n", msg );
      printblock( "msg[]", msg, size );
    
      encrypt( enc, msg, key, size, ksize );
      puts("***Warning***: Notice the first byte" );
      printblock( "enc[]", enc, size );
    
      decrypt( dec, enc, key, size, ksize );
      printblock( "dec[]", dec, size );
    
      dec[size] = '\0'; // marks the end of the string.
      printf( "Decoded text: \"%s\".\n", dec );
    }
    
    // prints the block pointed by p, with size bytes.
    void printblock( char *prompt, char *p, size_t size )
    {
      size_t offset = 0;
      char *oldp;
    
      oldp = p;
      printf( "%s:\n%08zx:", prompt, offset );
      while ( size-- )
      {
        printf( " %02x", *p );
        p++;
        offset++;
        if (p - oldp > 15)
        {
          oldp = p;
          printf("\n%08zx:", offset);
        }
      }
      puts("\n");
    }
    
    // We are not dealing with strings here, but with blocks of data.
    // Assumptions:
    //  encp, plainp and keyp are different pointers (should use 'restrict' here).
    //  encp is the only block pointed which will be changed ('enc' from 'encrypted text').
    //  plainp (pointer to plaintext) and keyp (pointer to key).
    //  tsize is the 'plain text' block size.
    //  ksize is the key size.
    void encrypt( char *encp, char *plainp, char *keyp, size_t tsize, size_t ksize )
    {
      char *kp = keyp;
      ssize_t ks = ksize;
    
      while ( tsize-- )
      {
        *encp++ = *plainp++ ^ *kp++;
    
        // Resets the auxiliary key pointer if we got at the
        // end of the key buffer...
        if ( --ks <= 0 )
        {
          ks = ksize;
          kp = keyp;
        }
      }
    }
    Result:
    Code:
    $ ./test
    Plain text: "Hello, world! I am a plain text!".
    
    msg[]:
    00000000: 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 20 49 20
    00000010: 61 6d 20 61 20 70 6c 61 69 6e 20 74 65 78 74 21
    00000020:
    
    ***Warning***: Notice the first byte
    enc[]:
    00000000: 00 20 20 20 20 64 65 3b 23 3d 24 21 6d 6c 06 68
    00000010: 24 21 6c 2e 68 35 20 2d 26 26 65 38 29 37 3c 64
    00000020:
    
    dec[]:
    00000000: 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 20 49 20
    00000010: 61 6d 20 61 20 70 6c 61 69 6e 20 74 65 78 74 21
    00000020:
    
    Decoded text: "Hello, world! I am a plain text!"
    The "encoded" part, printed with hd:
    Code:
    $ echo -ne "\x00\x20\x20\x20\x20\x64\x65\x3b\x23\x3d\x24\x21\x6d\x6c\x06\x68\x24\x21\x6c\x2e\x68\x35\x20\x2d\x26\x26\x65\x38\x29\x37\x3c\x64" | hd
    00000000  00 20 20 20 20 64 65 3b  23 3d 24 21 6d 6c 06 68  |.    de;#=$!ml.h|
    00000010  24 21 6c 2e 68 35 20 2d  26 26 65 38 29 37 3c 64  |$!l.h5 -&&e8)7<d|
    00000020
    Last edited by flp1969; 06-20-2019 at 08:08 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 08-02-2018, 10:10 AM
  2. Encryption and Decryption
    By dbz8gokugohan in forum C Programming
    Replies: 7
    Last Post: 12-02-2010, 07:40 AM
  3. encryption / decryption
    By ghatoz in forum C++ Programming
    Replies: 2
    Last Post: 11-18-2010, 06:45 AM
  4. Encryption/Decryption Help
    By coolage in forum C++ Programming
    Replies: 9
    Last Post: 04-25-2008, 01:53 AM
  5. Ask about Encryption and Decryption
    By ooosawaddee3 in forum C Programming
    Replies: 3
    Last Post: 07-19-2002, 12:55 AM

Tags for this Thread