#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gmp.h>
#define SIZE 37
#define PRIME_DIGITS 5
const char acList[SIZE] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b',
'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'm', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' '};
const char aacText[SIZE][PRIME_DIGITS + 1] = {"10037", "20101", "49121", "33151", "17029", "58013", "89867", "91199", "97259", "42683", "10061", "43487",
"49669", "74287", "98953", "75767", "74099", "12457", "32159", "53897", "41263", "60331", "33403", "91291", "43651", "40559",
"13921", "40531", "37861", "76091", "77093", "80107", "79861", "91801", "93937", "90397", "99989"};
const unsigned int auPassword[SIZE] = {89963, 85691, 79273, 49531, 30713, 63059, 59263, 70489, 26647, 39443, 59077, 77447, 46061, 20897, 48673,
78571, 65963, 15161, 64399, 45497, 91129, 80429, 42013, 17377, 19183, 23099, 22699, 55457, 84871, 84659, 32569, 80777, 52289,
86111, 86291, 37781, 94687};
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: CharInArrayChar
Summary: Search a given char in a given array char
Args: char cNeedle
Char to be searched.
char *acHaystack
Array of char to be looped.
unsigned int cacHaystack
Size of array.
Returns: int
If the char is founded returns the index, otherwise return -1.
-----------------------------------------------------------------F-F*/
int CharInArrayChar (const char cNeedle, const char *acHaystack, const unsigned int cacHaystack) {
for (unsigned int i = 0; i < cacHaystack; i++) {
if (acHaystack[i] == cNeedle) {
return i;
}
}
return -1;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: IntInArrayInt
Summary: Search a given integer in a given array integer
Args: char uNeedle
Char to be searched.
char *auHaystack
Array of char to be looped.
unsigned int cauHaystack
Size of array.
Returns: int
If the char is founded returns the index, otherwise return -1.
-----------------------------------------------------------------F-F*/
int IntInArrayInt (const unsigned int uNeedle, const unsigned int *auHaystack, const unsigned int cauHaystack) {
for (unsigned int i = 0; i < cauHaystack; i++) {
if (auHaystack[i] == uNeedle) {
return i;
}
}
return -1;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: StrInArrayStr
Summary: Search a given string in a given zero-terminated string array
Args: char acNeedle
Char to be searched.
char* aacHaystack
Array of char to be looped.
unsigned int caacHaystack
Size of array.
Returns: int
If the string is founded returns the index, otherwise return -1.
-----------------------------------------------------------------F-F*/
int StrInArrayStr (const char *acNeedle, const char aacHaystack[][PRIME_DIGITS + 1], const unsigned int caacHaystack) {
for (unsigned int i = 0; i < caacHaystack; i++) {
if (memcmp(acNeedle, aacHaystack[i], 5) == 0) {
return i;
}
}
return -1;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: SumPrimePassword
Summary: Convert a zero-terminated string into its sum of primes equivalent
Args: char *acPassword
Char to be searched.
unsigned int cbPassword
Size of array.
Returns: int
If the all the char in the password are valid return its sum, otherwise returns 0
-----------------------------------------------------------------F-F*/
long SumPrimePassword(const char *acPassword, unsigned int cbPassword) {
unsigned int uIndex;
long lSum = 0;
for (unsigned int i = 0; i < cbPassword; i++) {
uIndex = CharInArrayChar(acPassword[i], acList, SIZE);
if (uIndex < 0) {
return 0;
}
lSum += auPassword[uIndex];
}
return lSum;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: SumPrimeFromArray
Summary: Convert a unsigned int array containing char indexes into its sum of primes equivalent
Args: unsigned int *auState
Array of char indexes.
unsigned int csState
Size of array.
Returns: int
Return its sum
-----------------------------------------------------------------F-F*/
unsigned long SumPrimeFromArray(const unsigned int *auState, unsigned int cuState) {
unsigned long lSum = 0;
for (unsigned int i = 0; i < cuState; i++){
lSum += auPassword[auState[i]];
}
return lSum;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: EncodeTextToPrime
Summary: Convert a zero-terminated string into a zero-terminated string of its prime numbers representation
Args: char **pcCodifiedText
Pointer to the buffer where the final zero-terminated string is going to be stored.
char *acTextToCrypt
Zero terminated string to be converted.
unsigned int cbTextToCrypt
Size of string.
Returns: int
If all the char are valid return the size of the representation, otherwise return 0
-----------------------------------------------------------------F-F*/
int EncodeTextToPrime(char **pcCodifiedText, const char *acTextToCrypt, unsigned int cbTextToCrypt) {
unsigned int uIndex = 0, uCodifiedText = 0;
uCodifiedText = (cbTextToCrypt * PRIME_DIGITS) + 1;
*pcCodifiedText = (char*)calloc(uCodifiedText, sizeof(char));
for (unsigned int i = 0; i < cbTextToCrypt; i++) {
uIndex = CharInArrayChar(acTextToCrypt[i], acList, SIZE);
if (uIndex < 0) {
return 0;
}
strcat(*pcCodifiedText, aacText[uIndex]);
}
return uCodifiedText;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: DecodeTextToPrime
Summary: Convert a GMP number into a zero-terminated decodified string
Args: char *acDecodifiedText
Pointer to char where the decodied text will be stored
mpz_t mpzTextEncoded
Pointer to a structure from GMP library containing the number to be decodified
Returns: int
If all the char are valid return the size of the decodified text, otherwise return 0
-----------------------------------------------------------------F-F*/
int DecodePrimeToText(char *acDecodifiedText, const mpz_t mpzTextEncoded) {
unsigned int cbEncodedText = mpz_sizeinbase(mpzTextEncoded, 10);
int uIndex = 0;
char *acEncodedText = (char *)malloc(cbEncodedText + 2);
mpz_get_str(acEncodedText, 10, mpzTextEncoded);
for (unsigned int i = 0; i < (cbEncodedText / 5); i++) {
uIndex = StrInArrayStr(&acEncodedText[i * PRIME_DIGITS], aacText, SIZE);
if (uIndex < 0) {
return 0;
}
acDecodifiedText[i] = acList[uIndex];
}
free(acEncodedText);
return cbEncodedText / 5;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: EncryptText
Summary: Encrypt a zero-terminated string using a zero-terminated password
Args: mpz_t mpzResult
Pointer to a structure from GMP library that will contain the encrypted text
char *acTextToCrypt
Zero terminated string to be encrypted.
unsigned int cbTextToCrypt
Size of string.
char *acPassword
Zero terminated string containing the password.
unsigned int cbPassword
Size of string.
Returns: void
(none)
-----------------------------------------------------------------F-F*/
void EncryptText(mpz_t mpzResult, const char *acTextToCrypt, int cbTextToCrypt, const char *acPassword, int cbPassword) {
mpz_t pTempText;
mpz_init(pTempText);
char *acCodifiedText;
int cbCodifiedText = EncodeTextToPrime(&acCodifiedText, acTextToCrypt, cbTextToCrypt);
mpz_init_set_str(pTempText, acCodifiedText, 10);
free(acCodifiedText);
long lPassword = SumPrimePassword(acPassword, cbPassword);
mpz_mul_si(mpzResult, pTempText, lPassword);
mpz_clear(pTempText);
return;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: DecryptText
Summary: Decrypt a zero-terminated string using a zero-terminated password
Args: char *acDecryptedText
Pointer to the buffer where the decrypted text wil be stored
char *acTextToDecrypt
Zero terminated string to be decrypted.
unsigned int cbTextToDecrypt
Size of string.
char *acPassword
Zero terminated string containing the password.
unsigned int cbPassword
Size of string.
Returns: void
(none)
-----------------------------------------------------------------F-F*/
void DecryptText(char *acDecryptedText, const char *acTextToDecrypt, int cbTextToDecrypt, const char *acPassword, int cbPassword) {
unsigned long lRemainder;
mpz_t pTempHash, mpzResult;
mpz_init(pTempHash);
mpz_init(mpzResult);
long lPassword = SumPrimePassword(acPassword, cbPassword);
mpz_init_set_str(pTempHash, acTextToDecrypt, 10);
lRemainder = mpz_cdiv_q_ui(mpzResult, pTempHash, lPassword);
DecodePrimeToText(acDecryptedText, mpzResult);
mpz_clear(pTempHash);
mpz_clear(mpzResult);
return;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: ArrayByteToStr
Summary: Convert a array of indexes int it array of char representation
Args: char *acPassword
Pointer to the buffer where the password
unsigned int *auState
Array containing indexes
unsigned int cauState
Size of array.
Returns: void
(none)
-----------------------------------------------------------------F-F*/
void ArrayByteToStr(char *acPassword, const unsigned int *auState, const unsigned int cauState) {
for (unsigned int i = 0; i < cauState; i++) {
acPassword[i] = acList[auState[i]];
}
return;
}
/*F+F+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: UpdateState
Summary: Function that permits the Brute Force
Args: unsigned int **pauState
Pointer to the array of indexes
unsigned int *pcalState
Pointer to the size of the array
Returns: void
(none)
-----------------------------------------------------------------F-F*/
void UpdateState(unsigned int **pauState, unsigned int *pcalState) {
(*pauState)[*pcalState - 1]++;
for (int i = *pcalState - 1; i > -1; i--) {
if ((*pauState)[i] > (SIZE - 1)) {
if (i == 0) {
free(*pauState);
(*pcalState)++;
*pauState = (unsigned int *)calloc(*pcalState, sizeof(unsigned int));
return;
} else {
(*pauState)[i] = 0;
(*pauState)[i - 1]++;
}
}
}
return;
}
int main() {
char acText[254] = {NULL};
printf("hash: ");
scanf("%[^\n]%*c", acText);
clock_t tElapsedClock;
tElapsedClock = clock();
unsigned int cbText = strlen(acText);
unsigned long lAttemps = 0, lPassword, lRemainder, cacEncodedText, cacDecodedBuffer, lPrintable = 1000000;
unsigned int cauState = 1;
mpz_t pHash, pTemp;
mpz_init(pHash);
mpz_init(pTemp);
mpz_init_set_str(pHash, acText, 10);
unsigned int *auState = (unsigned int *)calloc(cauState, sizeof(unsigned int));
bool bSolved = false;
char *acDecodedBuffer;
while (0 == 0) {
lAttemps++;
lPassword = SumPrimeFromArray(auState, cauState);
lRemainder = mpz_cdiv_q_ui(pTemp, pHash, lPassword);
if (lRemainder == 0) {
cacEncodedText = mpz_sizeinbase(pTemp, 10);
acDecodedBuffer = (char *)calloc((cacEncodedText / 5) + 1, sizeof(char));
cacDecodedBuffer = DecodePrimeToText(acDecodedBuffer, pTemp);
if (cacDecodedBuffer > 0) {
bSolved = true;
break;
} else {
free(acDecodedBuffer);
}
}
if (0 == (lAttemps % lPrintable)) {
lPrintable *= 10;
printf("attemps: %d\tpass len: %d\n", lAttemps, cauState);
}
UpdateState(&auState, &cauState);
}
char *acPassword = (char *)calloc(cauState, sizeof(char));
ArrayByteToStr(acPassword, auState, cauState);
tElapsedClock = clock() - tElapsedClock;
double tElapsedTime = ((double)tElapsedClock) / CLOCKS_PER_SEC;
printf("--------------------\n");
printf("text: %s\n", acDecodedBuffer);
printf("--------------------\n");
printf("attemps: %d\ntime: %.2f s\npass: %s\n", lAttemps, tElapsedTime, acPassword);
free(acDecodedBuffer);
free(acPassword);
return 0;
}