Skip to content

Instantly share code, notes, and snippets.

@odzhan
Last active November 6, 2023 01:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odzhan/5131fe34398129aca6ba67b5d3a3e4b4 to your computer and use it in GitHub Desktop.
Save odzhan/5131fe34398129aca6ba67b5d3a3e4b4 to your computer and use it in GitHub Desktop.
Entropy reduction with Base-N encoding
//
// Non-standard implementation of Base-32 and Base-64 encoding to reduce entropy of data.
// Example results:
//
// Base-32 -> 1024 bytes : Before: 7.798637, After: 4.989102
// Base-64 -> 1024 bytes : Before: 7.805048, After: 5.971653
//
// The lower values after encoding show a reduction in entropy.
//
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <ctime>
#include <cmath>
#include <fcntl.h>
#if defined(_WIN32) || defined(_WIN64)
#define WINDOWS
#include <windows.h>
#if defined(_MSC_VER)
#pragma comment(lib, "advapi32")
#endif
#else
#define LINUX
#include <unistd.h>
#include <sys/types.h>
#endif
#if defined(BASE64)
// Base-64
#define BASE_N 6
#define CALC_ENC_SIZE(inlen) ((inlen + 2) / 3 * 4)
#else
// Base-32
#define BASE_N 5
#define CALC_ENC_SIZE(inlen) ((inlen + 4) / 5 * 8)
#endif
//
// Shannon entropy test.
//
double
shannon_entropy(void *inbuf, size_t len) {
uint8_t *in = (uint8_t*)inbuf;
double entropy = 0;
uint32_t frequency[256] = {0};
// Count the frequency of each byte value
for (size_t i=0; i<len; i++) {
frequency[in[i]]++;
}
// Calculate the entropy
for (size_t i=0; i<256; i++) {
if (frequency[i] > 0) {
double probability = (double) frequency[i] / len;
entropy -= probability * log2(probability);
}
}
return entropy;
}
//
// Base-N encoding and decoding.
//
void
base_n(size_t outlen, void *inbuf, void *outbuf, bool encode) {
uint8_t *out = (uint8_t*)outbuf;
uint8_t *in = (uint8_t*)inbuf;
uint32_t x = 0, z = 0;
uint8_t wl = 8, rl = BASE_N, mv = (1 << 8) - 1;
if (encode) {
rl = 8; // read length
wl = BASE_N; // write length
mv = (1 << BASE_N) - 1; // mask value
}
while (outlen) {
x = (x << rl) | *in++;
z += rl;
while (z >= wl) {
z -= wl;
*out++ = (x >> z) & mv;
outlen--;
}
}
}
void
print_hex(void *inbuf, size_t len) {
uint8_t *in = (uint8_t*)inbuf;
for (size_t i = 0; i < len; i++) {
printf("%02X ", in[i]);
if ((i + 1) % 16 == 0) {
printf("\n");
}
}
if (len % 16 != 0) {
printf("\n");
}
}
int
gen_random(void *buf, uint64_t len) {
#if defined(_WIN32)
HCRYPTPROV prov;
int ok;
// 1. acquire crypto context
if(!CryptAcquireContext(
&prov, NULL, NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) return 0;
ok = (int)CryptGenRandom(prov, (DWORD)len, (PBYTE)buf);
CryptReleaseContext(prov, 0);
return ok;
#else
int fd;
uint64_t r=0;
uint8_t *p=(uint8_t*)buf;
fd = open("/dev/urandom", O_RDONLY);
if(fd > 0) {
for(r=0; r<len; r++, p++) {
if(read(fd, p, 1) != 1) break;
}
close(fd);
}
return r == len;
#endif
}
int
main(int argc, char *argv[]) {
printf("\nEntropy reduction using Base-32 encoding. @modexpblog\n");
size_t inlen = 1024;
void *inbuf = calloc(inlen + 8, sizeof(char));
gen_random(inbuf, inlen);
// calculate encoded length
size_t enclen = CALC_ENC_SIZE(inlen);
void *encbuf = calloc(enclen, sizeof(char));
base_n(enclen, inbuf, encbuf, true);
printf("Base-%d encoding %zd bytes : Before: %lf, After: %lf\n",
(1 << BASE_N),
inlen,
shannon_entropy(inbuf, inlen),
shannon_entropy(encbuf, enclen)
);
void *decbuf = calloc(enclen, sizeof(char));
base_n(inlen, encbuf, decbuf, false);
free(inbuf);
free(encbuf);
free(decbuf);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment