Advertisement
Guest User

first

a guest
Mar 27th, 2015
237
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.03 KB | None | 0 0
  1. #include <stdio.h>    // printf
  2. #include <ctype.h>    // isxdigit in ascii_to_hex()
  3. #include <string.h>   // strncpy, strlen in main
  4. #include <stdint.h>   // uint32, uint8
  5. #include <stdlib.h>   // malloc, free
  6.  
  7. /* NOTE:
  8.    Usage: g++ -g -o first first.cpp
  9.    Run with name of executable (first in windows) or using ./first in linux.
  10.  
  11.    Research used: wikipedia article on base 64.
  12.    Extensive use of bit shifting.
  13.    steps:
  14.    1) Convert ascii encoding to hex encoding.
  15.    2) Divide input data into parts, each part being 3 bytes wide.
  16.    3) Divide 3 bytes into 4 parts of 6 bits each and convert to base 64.
  17.  */
  18.  
  19. uint32_t ascii_to_hex(char* chunk)
  20. {
  21.     uint32_t rval = 0;
  22.     uint8_t  shift = 0;
  23.    
  24.     for(int i = 5; i >= 0; i--)
  25.     {
  26.         if(isxdigit(chunk[i]) != 0)
  27.         {
  28.             // conversion using offsets
  29.             // shift is to arrange the individually converted
  30.             // hex digits into a 32 bit space.
  31.             if(isdigit(chunk[i]))
  32.                 rval += (chunk[i] - 48) << (4*shift);
  33.             else if(islower(chunk[i]))
  34.                 rval += (chunk[i] - 87) << (4*shift);
  35.             else
  36.                 rval += (chunk[i] - 55) << (4*shift);
  37.             shift += 1;
  38.         }
  39.     }
  40.     return rval;
  41. }
  42.  
  43. void b64_convert(char* chunk, char* result)
  44. {
  45.     uint32_t hex_chunk = ascii_to_hex(chunk);
  46.     // prepare for lookup
  47.     // NOTE: Remember that data is stored in a 32bit location. so highest 8 bits are always 0.
  48.     uint32_t first_chunk = (hex_chunk & (0xFC << 16)) >> 18;
  49.     uint32_t second_chunk = (hex_chunk & (0xFC << 10)) >> 12;
  50.     uint32_t third_chunk = (hex_chunk & (0xFC << 4)) >> 6;
  51.     uint32_t fourth_chunk = (hex_chunk & (0x3F));
  52.  
  53.     // lookup and print
  54.     static const char* lookup_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  55.     result[0] = lookup_table[first_chunk];
  56.     result[1] = lookup_table[second_chunk];
  57.     result[2] = lookup_table[third_chunk];
  58.     result[3] = lookup_table[fourth_chunk];
  59. }
  60.  
  61. int main(void)
  62. {
  63.     // NOTE: I assume that the length of the input hex data will always be an exact multiple of 6.
  64.     // Future todo could be to include some preprocessing code to ensure that.
  65.     static const char* ascii_data = "49276D206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
  66.     size_t input_len = strlen(ascii_data);
  67.     char* output = (char*)malloc((input_len/6)*4 + 1);
  68.     output[(input_len/6)*4] = '\0';
  69.     char* counter = output;
  70.     char temp[6] = "";
  71.    
  72.     while(input_len > 0)
  73.     {
  74.         strncpy(temp, ascii_data, 6);
  75.         b64_convert(temp, counter);
  76.         ascii_data += 6;
  77.         input_len -= 6;
  78.         counter += 4;
  79.     }
  80.    
  81.     printf("%s\n", output);
  82.     static const char* known_output = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t";
  83.     if(strcmp(output, known_output) == 0)
  84.         printf("Correct answer!\n");
  85.     else
  86.         printf("Incorrect answer! :-(\n");
  87.    
  88.     free(output);
  89.     return 0;
  90. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement