WaldaPepperCodeGenerator/PasswordUtil.cpp
2022-01-06 15:09:40 +01:00

199 lines
7.5 KiB
C++

/*
* PasswordUtil.cpp
*
* Created on: Dec 18, 2021
* Author: Goppier
*/
#include <stdio.h>
#include <string.h>
#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");
}