Thread: decoding

  1. #1
    Registered User
    Join Date
    Sep 2013
    Posts
    82

    decoding

    Hey,
    I have this text inside a txt file:

    harith
    as
    qw
    I am having some trouble encoding and decoding it, here is my code:
    Code:
    #include<stdio.h>
    
    decrypt(char    text[])
    {
         char       key = 'q';
         int        i;
         
         for(i = 0; i < strlen(text); i++)
         {
               text[i] = text[i] ^ key;
         }
    } 
    
    int main(void)
    {
        char      file[200];
        FILE      *fptr;
        
        fptr = fopen("password.txt","r");
        
       /*first encryption and decryption*/
        while(fgets(file,200,fptr) != NULL)
        {
             decrypt(file); //encrypt
             decrypt(file); //decrypt
             printf("%s",file);
        }
        
        /*second encryption and decryption*/
        int ch;
        while((ch = fgetc(fptr)) != EOF)
        {
             ch = ch ^ 'q'; //encrypt
             ch = ch ^ 'q'; //decrypt
             printf("%c",ch);
        } 
        
        system("pause");
        return 0;
    }
    here is the output I get:
    From first encryption and decryption;

    harith
    as
    From second encryption and decryption;

    harith
    as
    qw
    So why is first encryption and decryption not working?

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    your decrypt function uses strlen(text) (each loop iteration - but it is not the point)

    When string contains q character encrypted string will have 'q' ^ 'q' ==> 0 at this point

    So next call to decrypt will not go further and stop decoding on this point.

    You need to learn to use debugger
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Registered User
    Join Date
    Sep 2013
    Posts
    82
    Thanks!
    So is there a way around it?

  4. #4
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    For example - do not encrypt/decrypt 'q' character
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  5. #5
    Registered User
    Join Date
    Sep 2013
    Posts
    82
    Quote Originally Posted by vart View Post
    For example - do not encrypt/decrypt 'q' character
    then what should I do?

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Your problem, as vart said, is that 'q' ^ 'q' == '\0' and '\0' is interpreted by the string functions as the end of the string.

    You have three choices to fix it:
    1. Treat 'q' as a special case, possibly leaving it as 'q'.
    2. Instead of 'q', use a bit-pattern that won't occur in the input.
    3. Use the "mem" functions instead of the "str" functions.

    Quote Originally Posted by vart View Post
    your decrypt function uses strlen(text) (each loop iteration - but it is not the point)
    But the repeated calls to strlen will be optimized out when optimizations are active, so it's not such a terrible thing.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by oogabooga View Post

    But the repeated calls to strlen will be optimized out when optimizations are active, so it's not such a terrible thing.
    Except when the length of the string could be changed in the loop as in this case
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by vart View Post
    Except when the length of the string could be changed in the loop as in this case
    Good point. Dumb of me not to see that. Here's the loop with "gcc -O3" and it's using "repnz scas" to find the end of the string again and again within the loop, as you said. So it has inlined and optimized strlen, but of course hasn't moved it out of the loop.
    Code:
    401348: 80 34 16 71          xorb   $0x71,(%esi,%edx,1)
    40134c: 42                   inc    %edx
    40134d: 89 e9                mov    %ebp,%ecx
    40134f: 89 f7                mov    %esi,%edi
    401351: f2 ae                repnz scas %es:(%edi),%al
    401353: f7 d1                not    %ecx
    401355: 8d 59 ff             lea    -0x1(%ecx),%ebx
    401358: 39 da                cmp    %ebx,%edx
    40135a: 72 ec                jb     401348 <_decrypt+0x14>
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  9. #9
    11DE784A SirPrattlepod's Avatar
    Join Date
    Aug 2013
    Posts
    485
    Quote Originally Posted by vart View Post
    Except when the length of the string could be changed in the loop as in this case
    You're 100% correct of course... the question is (apart from your observation) how can the compiler know that strlen() is going to return the same value from strlen (or in general any function) for every iteration of the loop

  10. #10
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    It's interesting how much more "optimization" gcc will do if you take the strlen() call out of the loop. Optimization is an arcane art.
    Code:
    void decrypt(char *text) {
         char key = 'q';
         size_t i;
         size_t len = strlen(text);
         for (i = 0; i < len; i++)
               text[i] ^= key;
    }
    
    00401334 <_decrypt>:
      401334:    55                       push   %ebp
      401335:    57                       push   %edi
      401336:    56                       push   %esi
      401337:    53                       push   %ebx
      401338:    52                       push   %edx
    
      401339:    8b 5c 24 18              mov    0x18(%esp),%ebx
      40133d:    31 c0                    xor    %eax,%eax
      40133f:    b9 ff ff ff ff           mov    $0xffffffff,%ecx
      401344:    89 df                    mov    %ebx,%edi
    
      401346:    f2 ae                    repnz scas %es:(%edi),%al
      401348:    f7 d1                    not    %ecx
      40134a:    49                       dec    %ecx
      40134b:    74 58                    je     4013a5 <_decrypt+0x71>
    
      40134d:    89 d8                    mov    %ebx,%eax
      40134f:    f7 d8                    neg    %eax
      401351:    83 e0 03                 and    $0x3,%eax
      401354:    89 ce                    mov    %ecx,%esi
      401356:    39 c1                    cmp    %eax,%ecx
      401358:    77 52                    ja     4013ac <_decrypt+0x78>
      40135a:    83 f9 04                 cmp    $0x4,%ecx
      40135d:    77 51                    ja     4013b0 <_decrypt+0x7c>
      40135f:    89 ce                    mov    %ecx,%esi
      401361:    31 c0                    xor    %eax,%eax
      401363:    90                       nop
    
      401364:    80 34 03 71              xorb   $0x71,(%ebx,%eax,1)
      401368:    40                       inc    %eax
      401369:    39 f0                    cmp    %esi,%eax
      40136b:    72 f7                    jb     401364 <_decrypt+0x30>
    
      40136d:    39 f1                    cmp    %esi,%ecx
      40136f:    74 34                    je     4013a5 <_decrypt+0x71>
      401371:    89 cd                    mov    %ecx,%ebp
      401373:    29 f5                    sub    %esi,%ebp
      401375:    89 ef                    mov    %ebp,%edi
      401377:    c1 ef 02                 shr    $0x2,%edi
      40137a:    89 fa                    mov    %edi,%edx
      40137c:    c1 e2 02                 shl    $0x2,%edx
      40137f:    89 14 24                 mov    %edx,(%esp)
      401382:    74 18                    je     40139c <_decrypt+0x68>
    
      401384:    01 de                    add    %ebx,%esi
      401386:    31 d2                    xor    %edx,%edx
    
      401388:    81 34 96 71 71 71 71     xorl   $0x71717171,(%esi,%edx,4)
      40138f:    42                       inc    %edx
      401390:    39 d7                    cmp    %edx,%edi
      401392:    77 f4                    ja     401388 <_decrypt+0x54>
    
      401394:    03 04 24                 add    (%esp),%eax
      401397:    3b 2c 24                 cmp    (%esp),%ebp
      40139a:    74 09                    je     4013a5 <_decrypt+0x71>
    
      40139c:    80 34 03 71              xorb   $0x71,(%ebx,%eax,1)
      4013a0:    40                       inc    %eax
      4013a1:    39 c1                    cmp    %eax,%ecx
      4013a3:    77 f7                    ja     40139c <_decrypt+0x68>
    
      4013a5:    58                       pop    %eax
      4013a6:    5b                       pop    %ebx
      4013a7:    5e                       pop    %esi
      4013a8:    5f                       pop    %edi
      4013a9:    5d                       pop    %ebp
      4013aa:    c3                       ret    
    
      4013ac:    89 c6                    mov    %eax,%esi
      4013ae:    eb aa                    jmp    40135a <_decrypt+0x26>
      4013b0:    85 f6                    test   %esi,%esi
      4013b2:    75 ad                    jne    401361 <_decrypt+0x2d>
      4013b4:    31 c0                    xor    %eax,%eax
      4013b6:    eb b9                    jmp    401371 <_decrypt+0x3d>
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  11. #11
    Registered User
    Join Date
    Sep 2013
    Posts
    82
    Thanks guys. But I still don't understand the strlen thing, can some one please explain?
    And one more thing; if q ^ q = null ; then how come the second encryption and decryption worked?
    /*second encryption and decryption*/ int ch;
    while((ch = fgetc(fptr)) != EOF)
    {
    ch = ch ^ 'q'; //encrypt
    ch = ch ^ 'q'; //decrypt
    printf("%c",ch);
    }
    Last edited by Harith; 09-23-2013 at 11:15 PM.

  12. #12
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by Harith View Post
    Thanks guys. But I still don't understand the strlen thing, can some one please explain?
    And one more thing; if q ^ q = null ; then how come the second encryption and decryption worked?
    Putting the strlen() call in the test portion of the loop causes it to be executed on every iteration (with no chance of optimizing it out since its parameter is modified in the loop body). If instead you put it before the loop, storing the result in a variable that you use in the test portion of the loop, then it will only be executed once.


    As for 'q' ^ 'q' being 0, the problem is that this inserts a 0 into your string. Since 0 indicates the end of the string, it effectively truncates your string at that point.


    It works in the quoted portion above because you are not storing the result in a string this time, but simply applying the xor twice in a row to a single character and printing the result, which is the original ch.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  13. #13
    Registered User
    Join Date
    Sep 2013
    Posts
    82
    Quote Originally Posted by oogabooga View Post
    Putting the strlen() call in the test portion of the loop causes it to be executed on every iteration (with no chance of optimizing it out since its parameter is modified in the loop body). If instead you put it before the loop, storing the result in a variable that you use in the test portion of the loop, then it will only be executed once.


    As for 'q' ^ 'q' being 0, the problem is that this inserts a 0 into your string. Since 0 indicates the end of the string, it effectively truncates your string at that point.


    It works in the quoted portion above because you are not storing the result in a string this time, but simply applying the xor twice in a row to a single character and printing the result, which is the original ch.
    Thanks .

  14. #14
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    when you'll need to store the encoded result - and later decode it - you may think about base64 encoding of the "encoded" string.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Huffman decoding
    By dvargo1226 in forum C Programming
    Replies: 5
    Last Post: 08-17-2013, 08:28 AM
  2. Decoding
    By jugs in forum C Programming
    Replies: 2
    Last Post: 10-27-2009, 02:20 PM
  3. Code decoding
    By ash4741 in forum C++ Programming
    Replies: 6
    Last Post: 08-05-2009, 09:57 AM
  4. Help with decoding program...
    By porsche911nfs in forum C++ Programming
    Replies: 18
    Last Post: 04-10-2009, 12:21 AM
  5. Decoding
    By jk81 in forum C Programming
    Replies: 4
    Last Post: 11-12-2002, 11:24 PM

Tags for this Thread