From 33ecdaef69bd956789ae3ba9f65f54927d70421b Mon Sep 17 00:00:00 2001 From: Goppier <96147255+Goppier@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:09:40 +0100 Subject: [PATCH] Create PasswordUtil.cpp --- PasswordUtil.cpp | 198 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 PasswordUtil.cpp diff --git a/PasswordUtil.cpp b/PasswordUtil.cpp new file mode 100644 index 0000000..6c70e9f --- /dev/null +++ b/PasswordUtil.cpp @@ -0,0 +1,198 @@ +/* + * PasswordUtil.cpp + * + * Created on: Dec 18, 2021 + * Author: Goppier + */ + +#include +#include +#include "PasswordUtil.h" + +/** + * Prepares the given array with the correct order of values. + * + * @param array_code Pointer to array where the values can be placed in. + * @param wallpaper Struct that contains all the wallpaper parameters. + */ +void prepareArray(uint8_t *array_code, wallpaper_params_t wallpaper) +{ + uint8_t red = ((wallpaper.background_colour >> 16) & 0xff) >> 3; + uint8_t green = ((wallpaper.background_colour >> 8) & 0xff) >> 3; + uint8_t blue = (wallpaper.background_colour & 0xff) >> 3; + uint16_t bg_colour = (blue << 10) | (green << 5) | red; + + red = ((wallpaper.foreground_colour >> 16) & 0xff) >> 3; + green = ((wallpaper.foreground_colour >> 8) & 0xff) >> 3; + blue = (wallpaper.foreground_colour & 0xff) >> 3; + uint16_t fg_colour = (blue << 10) | (green << 5) | red; + + uint8_t x = (bg_colour & 0xff) ^ (fg_colour & 0xff) ^ wallpaper.icon ^ ((wallpaper.trainer_id >> 8) & 0xff); + uint8_t y = ((bg_colour >> 8) & 0xff) ^ ((fg_colour >> 8) & 0xff) ^ wallpaper.pattern ^ (wallpaper.trainer_id & 0xff); + + array_code[0] = (bg_colour & 0xff); + array_code[1] = ((bg_colour >> 8) & 0xff); + array_code[2] = (fg_colour & 0xff); + array_code[3] = ((fg_colour >> 8) & 0xff); + array_code[4] = wallpaper.icon; + array_code[5] = wallpaper.pattern; + array_code[6] = x; + array_code[7] = y; + array_code[8] = wallpaper.key; +} + +/** + * Bit shifts the entire array to the right a given amount of times. The array is seen as a circulair over the given range, + * meaning that bits loop back around to the beginning. + * + * First bits are shifted in groups of 8 (a byte). Afterwards there is one last loop for the leftover bits. + * + * @param array_code Pointer to array that contains the secret code in its current state + * @param range Range of bytes affected by the bitshift. + * @param bits_to_shift Total number of bits to shift. + */ +void bitShiftRight(uint8_t *array_code, uint8_t range, uint8_t bits_to_shift) +{ + uint8_t byte_shift = bits_to_shift / 8; + uint8_t leftover_bit_shift = bits_to_shift - byte_shift * 8; + + for (uint8_t x = 0; x < byte_shift; x++) + { + uint8_t temp = array_code[range]; // Save last value in array + memmove(&array_code[1], &array_code[0], range); // Move all affected bytes to the right + array_code[0] = temp; // Paste the saved value to the first spot in the array + } + + uint8_t temp_1 = 0; + uint8_t temp_2 = 0; + for (uint8_t x = 0; x <= range; x++) + { + temp_2 = ((array_code[x] << (8 - leftover_bit_shift)) & 0xff); // Save bits and bit shift to the left so it fits in the next byte + array_code[x] = array_code[x] >> leftover_bit_shift | temp_1; // Shift bits to the right and paste bits from previous byte behind it + temp_1 = temp_2; // Save temp_2 to temp_1 now that it has been used + } + array_code[0] |= temp_1; // Bits from the last byte need to loop back to the first byte +} + +/** + * Masks the entire array (except the key itself) with a mask created with the key. + * + * The most significant 4 bits of the key are masked over the entire array. + * + * @param array_code Pointer to array that contains the secret code in its current state + * @param range Key to create the mask with + */ +void maskArray(uint8_t *array_code, uint8_t key) +{ + uint8_t mask = key & 0b11110000; + mask = mask | (mask >> 4); + for (uint8_t x = 0; x < 8; x++) + { + array_code[x] ^= mask; + } +} + +/** + * Creates the English code that can be used to unlock the Wallpaper + * + * The code consists of 15 letters and each letter is 5 bits long. The array however only contains 72 bits (9 bytes). It is 3 bits too short. + * This solution to this is combining the last 2 bits with the first 3 bits of the first index of the array. + * + * @param array_code Pointer to array that contains the secret code in its current state + * @param english_code_buffer Pointer to the english code buffer to place the code into + */ +void createEnglishCode(uint8_t *array_code, english_letter_t *english_code_buffer) +{ + uint8_t u_index = 0; + uint8_t temp = 0; + uint8_t bits_to_shift = 0; + + for (uint8_t x = 0; x < 15; x++) + { + english_code_buffer[x] = (english_letter_t)((array_code[u_index] >> (bits_to_shift) | temp) >> (8 - 5)); // Create a new letter + bits_to_shift = (u_index + 1) * 8 - (x + 1) * 5; // Calculate the number of bits unused + temp = array_code[u_index] << (8 - bits_to_shift); // Save the unused bits + + if (bits_to_shift < 5) + { + u_index = (u_index < 8) ? u_index + 1 : 0; // Increase array index or loop back to zero if max is reached + } + } +} + +/** + * Prints the secret code to the terminal + * + * @param english_code_buffer Pointer to the english code buffer that contains the secret code + */ +void printSecretEnglishCode(english_letter_t *english_code_buffer) +{ + char password_string[16] = { 0 }; + for (uint8_t x = 0; x <= 14; x++) + { + switch (english_code_buffer[x]) + { + case B: password_string[x] = 'B'; break; + case C: password_string[x] = 'C'; break; + case D: password_string[x] = 'D'; break; + case F: password_string[x] = 'F'; break; + case G: password_string[x] = 'G'; break; + case H: password_string[x] = 'H'; break; + case J: password_string[x] = 'J'; break; + case K: password_string[x] = 'K'; break; + case L: password_string[x] = 'L'; break; + case M: password_string[x] = 'M'; break; + case N: password_string[x] = 'N'; break; + case P: password_string[x] = 'P'; break; + case Q: password_string[x] = 'Q'; break; + case R: password_string[x] = 'R'; break; + case S: password_string[x] = 'S'; break; + case T: password_string[x] = 'T'; break; + case V: password_string[x] = 'V'; break; + case W: password_string[x] = 'W'; break; + case Z: password_string[x] = 'Z'; break; + case b: password_string[x] = 'b'; break; + case c: password_string[x] = 'c'; break; + case d: password_string[x] = 'd'; break; + case f: password_string[x] = 'f'; break; + case g: password_string[x] = 'g'; break; + case h: password_string[x] = 'h'; break; + case j: password_string[x] = 'j'; break; + case k: password_string[x] = 'k'; break; + case m: password_string[x] = 'm'; break; + case n: password_string[x] = 'n'; break; + case p: password_string[x] = 'p'; break; + case q: password_string[x] = 'q'; break; + case s: password_string[x] = 's'; break; + } + } + printf("%s\n", password_string); +} + +/** + * Prints both the array and the created english code in binary form. This is only used for debugging + * + * @param array_code Pointer to array that contains the secret code in its current state + * @param english_code_buffer Pointer to the english code buffer that contains the secret code + */ +void printBinaryEnglishCode(uint8_t *array_code, english_letter_t *english_code) +{ + printf("What it should be:\n"); + printf("%c%c%c%c%c\n%c%c%c", BYTE_TO_BINARY(array_code[0])); + printf("%c%c\n%c%c%c%c%c\n%c", BYTE_TO_BINARY(array_code[1])); + printf("%c%c%c%c\n%c%c%c%c", BYTE_TO_BINARY(array_code[2])); + printf("%c\n%c%c%c%c%c\n%c%c", BYTE_TO_BINARY(array_code[3])); + printf("%c%c%c\n%c%c%c%c%c\n", BYTE_TO_BINARY(array_code[4])); + printf("%c%c%c%c%c\n%c%c%c", BYTE_TO_BINARY(array_code[5])); + printf("%c%c\n%c%c%c%c%c\n%c", BYTE_TO_BINARY(array_code[6])); + printf("%c%c%c%c\n%c%c%c%c", BYTE_TO_BINARY(array_code[7])); + printf("%c\n%c%c%c%c%c\n%c%c", BYTE_TO_BINARY(array_code[8])); + printf("%c%c%c\n\n", BYTE_TO_BINARY(array_code[0])); + + printf("What it is:\n"); + for (uint8_t x = 0; x <= 14; x++) + { + printf("%c%c%c%c%c\n", BYTE_TO_BINARY(english_code[x] << 3)); + } + printf("\n"); +}