I have written a program in C
, which encrypts and decrypts a c-styled string (const char *
) and print the result to stdout. It requires key (const char *)
and it's hash is calculated using Polynomial Rolling Hash.
My program makes sure that the hash of key
must be in-between 0...128
, using statement like size_t hash = get_hash(key) % 128;
. My code works well if I provide a good key
, but if the key
is bad (plain[i] ± hash < 0), then it exits saying could not encrypt
.
I have implemented all suggestion I got from my previous questions (not related this one).
Here's my code: TRY GOOD_KEY
| TRY BAD_KEY
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// gets hash of a string using Polynomial Rolling Hash
// https://en.wikipedia.org/wiki/Rolling_hash#Polynomial_rolling_hash
static size_t get_hash(const char *a)
{
if (a && *a != 0)
{
size_t p = 53;
size_t m = 1e9 + 9;
long long power_of_p = 1;
long long hash_val = 0;
for (size_t i = 0; a[i] != '\0'; i++)
{
hash_val = (hash_val + (a[i] - 97 + 1) * power_of_p) % m;
power_of_p = (power_of_p * p) % m;
}
return (hash_val % m + m) % m;
}
return (size_t)-1;
}
// encrypts `plain` using `key` and stores the output on heap allocated memory `out`
static bool encrypt(const char *plain, char **out, const char *key)
{
if (!plain || !out || !key)
return false;
size_t hash = get_hash(key) % 128;
size_t len = strlen(plain);
bool add = true;
*out = calloc(len + 1, sizeof(char));
if (!(*out))
return false;
for (size_t i = 0; plain[i] != '\0'; i++)
{
if (add == true && plain[i] + hash > '\0')
{
(*out)[i] = plain[i] + hash;
add = false;
}
else if (add == false && plain[i] - hash > '\0')// should not be less than zero
{
(*out)[i] = plain[i] - hash;
add = true;
}
else
{
free(*out);
return false;
}
}
return true;
}
// decrypts `enc` using `key` and stores the output on heap allocated memory `out`
static bool decrypt(const char *enc, char **out, const char *key)
{
if (!enc || !out || !key)
return false;
size_t hash = get_hash(key) % 128;
size_t len = strlen(enc);
bool add_inrv = true;
*out = calloc(len + 1, sizeof(char));
if (!(*out))
return false;
for (size_t i = 0; enc[i] != '\0'; i++)
{
if (add_inrv == true && enc[i] - hash > '\0')
{
(*out)[i] = enc[i] - hash;
add_inrv = false;
}
else if (add_inrv == false && enc[i] + hash > '\0')
{
(*out)[i] = enc[i] + hash;
add_inrv = true;
}
else
{
free(*out);
return false;
}
}
return true;
}
int main(int argc, char const **argv)
{
if (argc < 3)
{
perror("not enough input\nUsage: <MESSAGE> <KEY>");
return EXIT_FAILURE;
}
printf("Your text: `%s`\n", argv[1]);
char *enc, *after_dnc;
if(!encrypt(argv[1], &enc, argv[2])){
perror("could not encrypt");
return EXIT_FAILURE;
}
printf("Encrypted: `%s`\n", enc);
if(!decrypt(enc, &after_dnc, argv[2])){
perror("could not decrypt");
return EXIT_FAILURE;
}
printf("Decrypted: `%s`\n", after_dnc);
free(enc);
free(after_dnc);
return EXIT_SUCCESS;
}
For output please use online compiler given above.
I'm using GCC v11.2.0
on Arch Linux x86_64
using C17
standard.
char
s to have, or-42 % 128
? Are you comfortable with0 == hash(key)
? What type do you assumeplain[i] ± hash
to have? \$\endgroup\$