Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h> // printf
- #include <ctype.h> // isxdigit in ascii_to_hex()
- #include <string.h> // strncpy, strlen in main
- #include <stdint.h> // uint32, uint8
- #include <stdlib.h> // malloc, free
- /* NOTE:
- Usage: g++ -g -o first first.cpp
- Run with name of executable (first in windows) or using ./first in linux.
- Research used: wikipedia article on base 64.
- Extensive use of bit shifting.
- steps:
- 1) Convert ascii encoding to hex encoding.
- 2) Divide input data into parts, each part being 3 bytes wide.
- 3) Divide 3 bytes into 4 parts of 6 bits each and convert to base 64.
- */
- uint32_t ascii_to_hex(char* chunk)
- {
- uint32_t rval = 0;
- uint8_t shift = 0;
- for(int i = 5; i >= 0; i--)
- {
- if(isxdigit(chunk[i]) != 0)
- {
- // conversion using offsets
- // shift is to arrange the individually converted
- // hex digits into a 32 bit space.
- if(isdigit(chunk[i]))
- rval += (chunk[i] - 48) << (4*shift);
- else if(islower(chunk[i]))
- rval += (chunk[i] - 87) << (4*shift);
- else
- rval += (chunk[i] - 55) << (4*shift);
- shift += 1;
- }
- }
- return rval;
- }
- void b64_convert(char* chunk, char* result)
- {
- uint32_t hex_chunk = ascii_to_hex(chunk);
- // prepare for lookup
- // NOTE: Remember that data is stored in a 32bit location. so highest 8 bits are always 0.
- uint32_t first_chunk = (hex_chunk & (0xFC << 16)) >> 18;
- uint32_t second_chunk = (hex_chunk & (0xFC << 10)) >> 12;
- uint32_t third_chunk = (hex_chunk & (0xFC << 4)) >> 6;
- uint32_t fourth_chunk = (hex_chunk & (0x3F));
- // lookup and print
- static const char* lookup_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- result[0] = lookup_table[first_chunk];
- result[1] = lookup_table[second_chunk];
- result[2] = lookup_table[third_chunk];
- result[3] = lookup_table[fourth_chunk];
- }
- int main(void)
- {
- // NOTE: I assume that the length of the input hex data will always be an exact multiple of 6.
- // Future todo could be to include some preprocessing code to ensure that.
- static const char* ascii_data = "49276D206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
- size_t input_len = strlen(ascii_data);
- char* output = (char*)malloc((input_len/6)*4 + 1);
- output[(input_len/6)*4] = '\0';
- char* counter = output;
- char temp[6] = "";
- while(input_len > 0)
- {
- strncpy(temp, ascii_data, 6);
- b64_convert(temp, counter);
- ascii_data += 6;
- input_len -= 6;
- counter += 4;
- }
- printf("%s\n", output);
- static const char* known_output = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t";
- if(strcmp(output, known_output) == 0)
- printf("Correct answer!\n");
- else
- printf("Incorrect answer! :-(\n");
- free(output);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement