#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#define FILE_PATH "glass.bowl.candies.jpg"
#define NUM_ITERATIONS 1250000
#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
#define QR(a, b, c, d) ( \
a += b, d ^= a, d = ROTL(d, 16), \
c += d, b ^= c, b = ROTL(b, 12), \
a += b, d ^= a, d = ROTL(d, 8), \
c += d, b ^= c, b = ROTL(b, 7))
#define ROUNDS 20
// Function to read a binary file as bits
bool *read_binary_file_as_bits(const char *file_path, size_t *length) {
FILE *file = fopen(file_path, "rb");
if (!file) {
perror("Failed to open file");
exit(EXIT_FAILURE);
}
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
fseek(file, 0, SEEK_SET);
unsigned char *binary_data = (unsigned char *)malloc(file_size);
fread(binary_data, 1, file_size, file);
fclose(file);
*length = file_size * 8;
bool *truth_values = (bool *)malloc(*length * sizeof(bool));
for (long i = 0; i < file_size; ++i) {
for (int bit = 0; bit < 8; ++bit) {
truth_values[i * 8 + bit] = (binary_data[i] & (1 << bit)) != 0;
}
}
free(binary_data);
return truth_values;
}
// Function to calculate runs of truth values
int *calculate_runs(const bool *truth_values, size_t length, size_t *runs_length) {
int *runs = (int *)malloc(length * sizeof(int));
size_t index = 0;
int current_run_length = 1;
for (size_t i = 1; i < length; ++i) {
if (truth_values[i]) {
runs[index++] = current_run_length;
current_run_length = 1;
} else {
current_run_length++;
}
}
*runs_length = index;
return runs;
}
// Function to replace the first pair of runs
void replace_first_pair_of_runs(int *runs, size_t runs_length) {
if (runs_length >= 3) {
int run1 = runs[0];
int run2 = runs[1];
int run3 = runs[2];
if (run1 == run2 && run1 == 1) {
for (size_t i = 0; i < runs_length - 1; ++i) {
runs[i] = runs[i + 1];
}
runs[0] = 1;
} else {
int t = run1 + run2 - 1;
run2 = run1;
run1 = t;
if (run1 == run2) {
for (size_t i = 0; i < runs_length - 1; ++i) {
runs[i] = runs[i + 1];
}
runs[0] = run1;
runs[1] = run2 + run3 - 1;
} else {
runs[0] = run1;
runs[1] = run2;
}
}
}
}
// Function to generate a sequence of truth values from runs
bool *true_false_sequence(const int *runs, size_t runs_length, size_t *length) {
size_t total_length = 0;
for (size_t i = 0; i < runs_length; ++i) {
total_length += runs[i];
}
bool *truth_values = (bool *)malloc(total_length * sizeof(bool));
size_t index = 0;
for (size_t i = 0; i < runs_length; ++i) {
for (int j = 0; j < runs[i] - 1; ++j) {
truth_values[index++] = true;
}
truth_values[index++] = false;
}
*length = total_length;
return truth_values;
}
// Chacha20 block function for generating pseudorandom values
void chacha_block(uint32_t out[16], uint32_t const in[16]) {
int i;
uint32_t x[16];
for (i = 0; i < 16; ++i)
x[i] = in[i];
for (i = 0; i < ROUNDS; i += 2) {
QR(x[0], x[4], x[ 8], x[12]);
QR(x[1], x[5], x[ 9], x[13]);
QR(x[2], x[6], x[10], x[14]);
QR(x[3], x[7], x[11], x[15]);
QR(x[0], x[5], x[10], x[15]);
QR(x[1], x[6], x[11], x[12]);
QR(x[2], x[7], x[ 8], x[13]);
QR(x[3], x[4], x[ 9], x[14]);
}
for (i = 0; i < 16; ++i)
out[i] = x[i] + in[i];
}
// Function to generate pseudorandom truth values
void generate_pseudorandom_truths(uint32_t seed, int count, int truths[]) {
uint32_t input[16] = {
0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
0x00000001, seed, 0x4a000000, 0x00000000
};
uint32_t output[16];
int i, j;
for (i = 0; i < count; ++i) {
chacha_block(output, input);
for (j = 0; j < 16 && i < count; ++j, ++i) {
truths[i] = output[j] & 1;
}
}
}
// Function to XOR truth values with pseudorandom truth values
void xor_truth_values(uint32_t *current_seed, bool *truth_values, size_t length) {
int count = length;
int *pseudorandom_truths = (int *)malloc(count * sizeof(int));
generate_pseudorandom_truths(*current_seed, count, pseudorandom_truths);
for (size_t i = 0; i < 16; ++i) {
truth_values[i] ^= pseudorandom_truths[i % count];
}
free(pseudorandom_truths);
*current_seed -= 133;
}
// Main processing function
bool *process_runs(uint32_t current_seed, const char *file_path, size_t num_iterations, size_t *final_length) {
size_t length;
bool *truth_values = read_binary_file_as_bits(file_path, &length);
for (size_t i = 0; i < num_iterations; ++i) {
size_t runs_length;
int *runs = calculate_runs(truth_values, length, &runs_length);
replace_first_pair_of_runs(runs, runs_length);
free(truth_values);
truth_values = true_false_sequence(runs, runs_length, &length);
free(runs);
xor_truth_values(¤t_seed, truth_values, length);
}
*final_length = length;
return truth_values;
}
// Function to transform truth values to binary bytes
unsigned char *truth_values_to_binary_bytes(const bool *truth_values, size_t length) {
unsigned char *binary_bytes = (unsigned char *)malloc(length * sizeof(unsigned char));
for (size_t i = 0; i < length; ++i) {
binary_bytes[i] = truth_values[i] ? 0xFF : 0x00;
}
return binary_bytes;
}
int main() {
uint32_t current_seed = 0x31515433; // Example seed
size_t num_iterations = NUM_ITERATIONS;
size_t final_length;
bool *final_bits = process_runs(current_seed, FILE_PATH, num_iterations, &final_length);
unsigned char *binary_bytes = truth_values_to_binary_bytes(final_bits, final_length);
free(final_bits);
FILE *output_file = fopen("output.bin", "wb");
if (!output_file) {
perror("Failed to open output file");
free(binary_bytes);
exit(EXIT_FAILURE);
}
fwrite(binary_bytes, 1, final_length, output_file);
fclose(output_file);
free(binary_bytes);
printf("Binary output has been written to output.bin\n");
printf("Final length: %zu\n", final_length);
return 0;
}