NaraMotion / c_src /blend2d_license.cpp
ArifiIslam's picture
Release NaraMotion v0.26.0: Structure of Arrays (SoA), Path Arena Allocator, Uniform Grid Indexing, Dual-Buffer Rendering & Centroid Spring Pop-in
b516e00 verified
Raw History Blame Contribute Delete
11.3 kB
// ============================================================================
// NaraMotion Native Cryptographic Licensing & Anti-Tamper Watermark Engine
// Author: Islam Arifi
// License: Proprietary
// ============================================================================
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#ifdef _WIN32
#define BL_LICENSE_API extern "C" __declspec(dllexport)
#else
#define BL_LICENSE_API extern "C" __attribute__((visibility("default")))
#endif
// ============================================================================
// SHA-256 Engine (Self-Contained in C++)
// ============================================================================
typedef struct {
uint32_t state[8];
uint64_t count;
uint8_t buffer[64];
} SHA256_CTX;
#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define SIG0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define SIG1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define GAM0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3))
#define GAM1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10))
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
static void sha256_transform(SHA256_CTX* ctx, const uint8_t data[64]) {
uint32_t W[64];
for (int i = 0; i < 16; ++i) {
W[i] = ((uint32_t)data[i * 4] << 24) |
((uint32_t)data[i * 4 + 1] << 16) |
((uint32_t)data[i * 4 + 2] << 8) |
((uint32_t)data[i * 4 + 3]);
}
for (int i = 16; i < 64; ++i) {
W[i] = GAM1(W[i - 2]) + W[i - 7] + GAM0(W[i - 15]) + W[i - 16];
}
uint32_t a = ctx->state[0], b = ctx->state[1], c = ctx->state[2], d = ctx->state[3];
uint32_t e = ctx->state[4], f = ctx->state[5], g = ctx->state[6], h = ctx->state[7];
for (int i = 0; i < 64; ++i) {
uint32_t T1 = h + SIG1(e) + CH(e, f, g) + K[i] + W[i];
uint32_t T2 = SIG0(a) + MAJ(a, b, c);
h = g; g = f; f = e; e = d + T1;
d = c; c = b; b = a; a = T1 + T2;
}
ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d;
ctx->state[4] += e; ctx->state[5] += f; ctx->state[6] += g; ctx->state[7] += h;
}
static void sha256_init(SHA256_CTX* ctx) {
ctx->state[0] = 0x6a09e667; ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372; ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f; ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab; ctx->state[7] = 0x5be0cd19;
ctx->count = 0;
}
static void sha256_update(SHA256_CTX* ctx, const uint8_t* data, size_t len) {
size_t left = (size_t)(ctx->count & 0x3F);
ctx->count += len;
size_t fill = 64 - left;
if (left && len >= fill) {
memcpy(ctx->buffer + left, data, fill);
sha256_transform(ctx, ctx->buffer);
data += fill;
len -= fill;
left = 0;
}
while (len >= 64) {
sha256_transform(ctx, data);
data += 64;
len -= 64;
}
if (len) {
memcpy(ctx->buffer + left, data, len);
}
}
static void sha256_final(SHA256_CTX* ctx, uint8_t digest[32]) {
uint8_t final_count[8];
uint64_t bits = ctx->count * 8;
for (int i = 0; i < 8; ++i) {
final_count[i] = (uint8_t)((bits >> ((7 - i) * 8)) & 0xFF);
}
static const uint8_t pad[64] = { 0x80 };
size_t pad_len = ((size_t)(ctx->count & 0x3F) < 56) ? (56 - (size_t)(ctx->count & 0x3F)) : (120 - (size_t)(ctx->count & 0x3F));
sha256_update(ctx, pad, pad_len);
sha256_update(ctx, final_count, 8);
for (int i = 0; i < 8; ++i) {
digest[i * 4] = (uint8_t)((ctx->state[i] >> 24) & 0xFF);
digest[i * 4 + 1] = (uint8_t)((ctx->state[i] >> 16) & 0xFF);
digest[i * 4 + 2] = (uint8_t)((ctx->state[i] >> 8) & 0xFF);
digest[i * 4 + 3] = (uint8_t)(ctx->state[i] & 0xFF);
}
}
// ============================================================================
// Obfuscated Salt & Key Verification
// ============================================================================
// Salt XOR masked
static const uint8_t k_salt[] = "NaraMotion_Auras_2026_SecureSalt_IslamArifi";
// Target SHA256 of (key + salt) XOR masked with 0x5A
static const uint8_t k_obf_hash[32] = {
28, 124, 74, 156, 138, 255, 148, 152, 72, 50, 36, 52, 221, 184, 30, 140,
81, 227, 221, 39, 219, 112, 123, 64, 90, 193, 98, 233, 193, 113, 93, 215
};
// Global license activation state (0 = Unlicensed Evaluation, 1 = Fully Activated)
static volatile int g_license_active = 0;
BL_LICENSE_API int bl_license_verify(const char* key) {
if (!key) return 0;
size_t key_len = strlen(key);
if (key_len == 0 || key_len > 128) return 0;
SHA256_CTX ctx;
sha256_init(&ctx);
sha256_update(&ctx, (const uint8_t*)key, key_len);
sha256_update(&ctx, k_salt, strlen((const char*)k_salt));
uint8_t digest[32];
sha256_final(&ctx, digest);
// Constant-time XOR comparison
int diff = 0;
for (int i = 0; i < 32; ++i) {
uint8_t unmasked = k_obf_hash[i] ^ 0x5A;
diff |= (digest[i] ^ unmasked);
}
if (diff == 0) {
g_license_active = 1;
return 1;
}
return 0;
}
BL_LICENSE_API int bl_license_is_active(void) {
return g_license_active;
}
BL_LICENSE_API void bl_license_reset(void) {
g_license_active = 0;
}
// ============================================================================
// High-Performance Native Watermark ("Auras") Compositor
// ============================================================================
// 5x7 Vector Glyph Definitions for "A U R A S"
static const uint8_t GLYPH_A[7] = {
0b01110,
0b10001,
0b10001,
0b11111,
0b10001,
0b10001,
0b10001
};
static const uint8_t GLYPH_U[7] = {
0b10001,
0b10001,
0b10001,
0b10001,
0b10001,
0b10001,
0b01110
};
static const uint8_t GLYPH_R[7] = {
0b11110,
0b10001,
0b10001,
0b11110,
0b10100,
0b10010,
0b10001
};
static const uint8_t GLYPH_S[7] = {
0b01111,
0b10000,
0b10000,
0b01110,
0b00001,
0b00001,
0b11110
};
static inline void blend_pixel_32(uint32_t* dst, uint8_t sr, uint8_t sg, uint8_t sb, uint8_t sa) {
uint32_t d = *dst;
uint8_t da = (uint8_t)(d >> 24);
uint8_t dr = (uint8_t)(d >> 16);
uint8_t dg = (uint8_t)(d >> 8);
uint8_t db = (uint8_t)(d);
uint32_t inv_a = 255 - sa;
uint8_t out_r = (uint8_t)((sr * sa + dr * inv_a) / 255);
uint8_t out_g = (uint8_t)((sg * sa + dg * inv_a) / 255);
uint8_t out_b = (uint8_t)((sb * sa + db * inv_a) / 255);
uint8_t out_a = (uint8_t)(sa + (da * inv_a) / 255);
*dst = ((uint32_t)out_a << 24) | ((uint32_t)out_r << 16) | ((uint32_t)out_g << 8) | (uint32_t)out_b;
}
static void draw_glyph(uint32_t* pixels, int w, int h, int stride_pixels, int start_x, int start_y, int scale, const uint8_t glyph[7], uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
for (int row = 0; row < 7; ++row) {
uint8_t bits = glyph[row];
for (int col = 0; col < 5; ++col) {
if ((bits >> (4 - col)) & 1) {
// Draw scale x scale block
for (int dy = 0; dy < scale; ++dy) {
int py = start_y + row * scale + dy;
if (py < 0 || py >= h) continue;
for (int dx = 0; dx < scale; ++dx) {
int px = start_x + col * scale + dx;
if (px < 0 || px >= w) continue;
blend_pixel_32(&pixels[py * stride_pixels + px], r, g, b, a);
}
}
}
}
}
}
BL_LICENSE_API void bl_license_apply_watermark_if_unlicensed(uint32_t* pixels, int width, int height, int stride_bytes) {
if (g_license_active) {
return; // Licensed: 0.00% overhead, instant return
}
if (!pixels || width <= 0 || height <= 0) return;
int stride_pixels = stride_bytes / sizeof(uint32_t);
// Calculate watermark size relative to image dimensions
int min_dim = width < height ? width : height;
int scale = min_dim / 35;
if (scale < 2) scale = 2;
if (scale > 24) scale = 24;
int letter_width = 5 * scale;
int letter_height = 7 * scale;
int letter_spacing = 2 * scale;
int total_width = (letter_width * 5) + (letter_spacing * 4);
int start_x = (width - total_width) / 2;
int start_y = (height - letter_height) / 2;
// 1. Draw subtle semi-transparent background dark badge behind "Auras"
int pad_x = 4 * scale;
int pad_y = 3 * scale;
int box_x0 = start_x - pad_x;
int box_y0 = start_y - pad_y;
int box_x1 = start_x + total_width + pad_x;
int box_y1 = start_y + letter_height + pad_y;
if (box_x0 < 0) box_x0 = 0;
if (box_y0 < 0) box_y0 = 0;
if (box_x1 >= width) box_x1 = width - 1;
if (box_y1 >= height) box_y1 = height - 1;
for (int y = box_y0; y <= box_y1; ++y) {
for (int x = box_x0; x <= box_x1; ++x) {
blend_pixel_32(&pixels[y * stride_pixels + x], 5, 8, 18, 90); // 35% dark slate
}
}
// 2. Draw "AURAS" watermark letters in semi-transparent cyan / white (30% alpha = ~75)
uint8_t alpha = 85;
uint8_t r = 56, g = 189, b = 248; // #38BDF8 Cyan
uint8_t r_w = 240, g_w = 245, b_w = 255; // White glow
int cur_x = start_x;
// 'A'
draw_glyph(pixels, width, height, stride_pixels, cur_x, start_y, scale, GLYPH_A, r, g, b, alpha);
cur_x += letter_width + letter_spacing;
// 'U'
draw_glyph(pixels, width, height, stride_pixels, cur_x, start_y, scale, GLYPH_U, r, g, b, alpha);
cur_x += letter_width + letter_spacing;
// 'R'
draw_glyph(pixels, width, height, stride_pixels, cur_x, start_y, scale, GLYPH_R, r_w, g_w, b_w, alpha + 15);
cur_x += letter_width + letter_spacing;
// 'A'
draw_glyph(pixels, width, height, stride_pixels, cur_x, start_y, scale, GLYPH_A, r, g, b, alpha);
cur_x += letter_width + letter_spacing;
// 'S'
draw_glyph(pixels, width, height, stride_pixels, cur_x, start_y, scale, GLYPH_S, r, g, b, alpha);
}