Skip to content

Instantly share code, notes, and snippets.

@odzhan
Last active April 29, 2024 09:03
Show Gist options
  • Save odzhan/209275e08bf6b770de8b553d759d5d5c to your computer and use it in GitHub Desktop.
Save odzhan/209275e08bf6b770de8b553d759d5d5c to your computer and use it in GitHub Desktop.
Data Masking with Byte Substitution
//
// @modexpblog
//
#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(USE64)
//
// SPECK128-256
//
#define WORDLEN 64
#define PRNG_MAX_INT (INT64_MAX + 1)
#define ENCRYPT_KEY_LEN 32
#define ENCRYPT_BLOCK_LEN 16
#define R(v,n)(((v)>>(n))|((v)<<(64-(n))))
typedef unsigned long long W;
void
encrypt(void*mk,void*p){
W k[4],*x=(W*)p,i,t;
for (i=0; i<4; i++) k[i] = ((W*)mk)[i];
for (i=0; i<34; i++) {
x[1] = (R(x[1], 8) + x[0]) ^ k[0],
x[0] = R(x[0], 61) ^ x[1],
k[1] = (R(k[1], 8) + k[0]) ^ i,
k[0] = R(k[0], 61) ^ k[1];
t = k[1], k[1] = k[2], k[2] = k[3], k[3] = t;
}
}
#else
//
// SPECK64-128
//
#define WORDLEN 32
#define PRNG_MAX_INT (INT32_MAX + 1)
#define ENCRYPT_KEY_LEN 16
#define ENCRYPT_BLOCK_LEN 8
#define R(v,n)(((v)>>(n))|((v)<<(32-(n))))
typedef unsigned int W;
void
encrypt(void* mk, void* p) {
W k[4],*x=(W*)p,i,t;
for (i=0; i<4; i++) k[i] = ((W*)mk)[i];
for (i=0; i<27; i++) {
x[0] = (R(x[0], 8) + x[1]) ^ k[0],
x[1] = R(x[1], 29) ^ x[0],
t = k[3],
k[3] = (R(k[1], 8) + k[0]) ^ i,
k[0] = R(k[0], 29) ^ k[3],
k[1] = k[2], k[2]=t;
}
}
#endif
W
prng_word(void *key, W max) {
W r, x[2], ctr = 1, d = ((-max) / max) + 1;
if (d == 0) return 0;
for (;;) {
x[0] = max;
x[1] = ctr++;
encrypt(key, x);
r = x[0] / d;
if (r < max) return r;
}
}
void
shuffle(void *seed, void *inbuf, size_t inlen) {
uint8_t *in = (uint8_t*)inbuf;
for (size_t i = inlen - 1; i > 0; i--) {
uint32_t j = prng_word(seed, (i + 1));
uint8_t t = in[i];
in[i] = in[j];
in[j] = t;
}
}
void
unshuffle(void *seed, void *inbuf, size_t inlen) {
uint8_t *in = (uint8_t*)inbuf;
for (size_t i = 0; i < inlen; i++) {
uint32_t j = prng_word(seed, (i + 1));
uint8_t t = in[i];
in[i] = in[j];
in[j] = t;
}
}
int
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
}
//
// simple byte substitution using fisher-yates shuffle and DRBG
//
typedef struct _mask_ctx {
uint8_t sbox[256], sbox_inv[256];
} mask_ctx;
void
init_mask(mask_ctx *c) {
uint8_t seed[ENCRYPT_KEY_LEN];
// initialise sbox
for (int i=0; i<256; i++) {
c->sbox[i] = (uint8_t)i;
}
// initialise seed
random(seed, ENCRYPT_KEY_LEN);
// shuffle sbox using random seed.
shuffle(seed, c->sbox, 256);
// create inverse
for (int i=0; i<256; i++) {
c->sbox_inv[c->sbox[i]] = i;
}
}
// mask buf
void
encode(mask_ctx *c, void *buf, size_t len) {
uint8_t *x = (uint8_t*)buf;
for (size_t i=0; i<len; i++) {
x[i] = c->sbox[x[i]];
}
}
// unmask buf
void
decode(mask_ctx *c, void *buf, size_t len) {
uint8_t *x = (uint8_t*)buf;
for (size_t i=0; i<len; i++) {
x[i] = c->sbox_inv[x[i]];
}
}
void
dump(const char *str, void *buf, size_t len) {
uint8_t *x = (uint8_t*)buf;
printf("\n%s:\n", str);
for (size_t i=0; i<len; i++) {
printf(" %02X", x[i]);
}
}
int
main(int argc, char *argv[]) {
mask_ctx c;
uint8_t buf[32];
// using random bytes here for testing..
random(buf, sizeof(buf));
init_mask(&c);
dump("raw", buf, sizeof(buf));
encode(&c, buf, sizeof(buf));
dump("encoded", buf, sizeof(buf));
decode(&c, buf, sizeof(buf));
dump("decoded", buf, sizeof(buf));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment