mirror of
git://f0xx.org/android_cast
synced 2026-07-29 06:39:09 +03:00
docs, obfuscation
This commit is contained in:
122
ndk/obfuscate/obfuscate.c
Normal file
122
ndk/obfuscate/obfuscate.c
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "obfuscate.h"
|
||||
#include <stddef.h>
|
||||
|
||||
static uint16_t rotl16(uint16_t x, unsigned int n)
|
||||
{
|
||||
n &= 15u;
|
||||
return (uint16_t)((x << n) | (x >> (16u - n)));
|
||||
}
|
||||
|
||||
static uint64_t rotl40(uint64_t x, unsigned int n)
|
||||
{
|
||||
n %= OBF_PAYLOAD_BITS;
|
||||
x &= OBF_PAYLOAD_MASK;
|
||||
if (n == 0u)
|
||||
return x;
|
||||
return ((x << n) | (x >> (OBF_PAYLOAD_BITS - n))) & OBF_PAYLOAD_MASK;
|
||||
}
|
||||
|
||||
static uint64_t rotr40(uint64_t x, unsigned int n)
|
||||
{
|
||||
n %= OBF_PAYLOAD_BITS;
|
||||
x &= OBF_PAYLOAD_MASK;
|
||||
if (n == 0u)
|
||||
return x;
|
||||
return ((x >> n) | (x << (OBF_PAYLOAD_BITS - n))) & OBF_PAYLOAD_MASK;
|
||||
}
|
||||
|
||||
/* Lightweight seed mixer — same output for same seed on any platform. */
|
||||
static uint64_t derive_key(uint64_t seed)
|
||||
{
|
||||
uint64_t x = seed ^ 0xA5A5A5A5A5A5A5A5ULL;
|
||||
|
||||
x ^= x >> 33;
|
||||
x *= 0xFF51AFD7ED558CCDULL;
|
||||
x ^= x >> 33;
|
||||
x *= 0xC4CEB9FE1A85EC53ULL;
|
||||
x ^= x >> 33;
|
||||
return x & OBF_PAYLOAD_MASK;
|
||||
}
|
||||
|
||||
static unsigned int derive_rotation(uint64_t seed)
|
||||
{
|
||||
uint64_t mix = seed * 0x9E3779B97F4A7C15ULL;
|
||||
|
||||
return (unsigned int)((mix >> 59) + 1u); /* 1..8 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 24-bit FEC-style tag: four 16-bit shards XOR-mixed with key and seed.
|
||||
* Detects single-bit flips and wrong seed with high probability.
|
||||
*/
|
||||
static uint32_t compute_tag(uint64_t val, uint64_t seed)
|
||||
{
|
||||
uint64_t k = derive_key(seed);
|
||||
uint64_t a = (val & 0xFFFFULL) ^ (k & 0xFFFFULL);
|
||||
uint64_t b = ((val >> 16) & 0xFFFFULL) ^ ((k >> 16) & 0xFFFFULL);
|
||||
uint64_t c = ((val >> 32) & 0xFFFFULL) ^ ((k >> 32) & 0xFFFFULL);
|
||||
uint64_t d = ((val >> 48) & 0xFFFFULL) ^ ((k >> 48) & 0xFFFFULL);
|
||||
uint64_t p1 = a ^ rotl16((uint16_t)b, 3) ^ c;
|
||||
uint64_t p2 = b ^ rotl16((uint16_t)c, 7) ^ d;
|
||||
uint64_t p3 = c ^ rotl16((uint16_t)d, 11) ^ a;
|
||||
uint64_t mix = (p1 * 0x01000193ULL) ^ (p2 << 16) ^ (p3 << 8);
|
||||
|
||||
mix ^= seed;
|
||||
mix *= 0x85EBCA77C2B2AE63ULL;
|
||||
mix ^= mix >> 33;
|
||||
return (uint32_t)(mix & 0xFFFFFFULL);
|
||||
}
|
||||
|
||||
static uint64_t obfuscate(uint64_t val, uint64_t seed)
|
||||
{
|
||||
uint64_t key = derive_key(seed);
|
||||
unsigned int rot = derive_rotation(seed);
|
||||
|
||||
return rotl40(val & OBF_PAYLOAD_MASK, rot) ^ key;
|
||||
}
|
||||
|
||||
static uint64_t deobfuscate(uint64_t obscured, uint64_t seed)
|
||||
{
|
||||
uint64_t key = derive_key(seed);
|
||||
unsigned int rot = derive_rotation(seed);
|
||||
|
||||
return rotr40(obscured ^ key, rot);
|
||||
}
|
||||
|
||||
int32_t encode(uint64_t val, uint64_t seed, uint64_t *out)
|
||||
{
|
||||
uint64_t packed;
|
||||
uint32_t tag;
|
||||
|
||||
if (out == NULL)
|
||||
return OBF_ERR_NULL;
|
||||
if (val > OBF_PAYLOAD_MASK)
|
||||
return OBF_ERR_RANGE;
|
||||
|
||||
tag = compute_tag(val, seed);
|
||||
packed = ((uint64_t)tag << OBF_PAYLOAD_BITS) | obfuscate(val, seed);
|
||||
*out = packed;
|
||||
return OBF_OK;
|
||||
}
|
||||
|
||||
int32_t decode(uint64_t encoded_val, uint64_t seed, uint64_t *out)
|
||||
{
|
||||
uint32_t stored_tag;
|
||||
uint32_t expected_tag;
|
||||
uint64_t obscured;
|
||||
uint64_t val;
|
||||
|
||||
if (out == NULL)
|
||||
return OBF_ERR_NULL;
|
||||
|
||||
stored_tag = (uint32_t)(encoded_val >> OBF_PAYLOAD_BITS);
|
||||
obscured = encoded_val & OBF_PAYLOAD_MASK;
|
||||
val = deobfuscate(obscured, seed);
|
||||
expected_tag = compute_tag(val, seed);
|
||||
|
||||
if (stored_tag != expected_tag)
|
||||
return OBF_ERR_VERIFY;
|
||||
|
||||
*out = val;
|
||||
return OBF_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user