Scarab
A thin, game-agnostic 2D engine host built on the sunlight tile-map engine
Loading...
Searching...
No Matches
Scarab::Engine::Lua::LuaCryptoApi Class Reference

Content encryption - protects a game's own .zip bundle content so only that game's own privately-built scarab executable can read it back. See the root README.md's own "Content encryption" section and tools/README.md for the full design/workflow. More...

#include <luacryptoapi.h>

Static Public Member Functions

static void Register (lua_State *pLuaState)
 Register the content-encryption Lua-callable functions. sodium_init() is called once here rather than lazily inside EncryptData/DecryptData - Register() itself already only ever runs once, at engine startup, matching every other Lua*Api's own one-time setup (e.g. RaylibEngine's constructor registering it's own raylib callback once). libsodium's own docs describe sodium_init() as safe to call more than once regardless, so this isn't strictly required for correctness - just the more explicit, "set up once at startup" shape this codebase already follows elsewhere.
 
static bool TryDecryptBytes (const std ::vector< unsigned char > &data, std ::vector< unsigned char > &out)
 Attempt to decrypt a buffer that may have been produced by crypto_encrypt_data/tools/pack.lua, using this build's own SCARAB_CONTENT_KEY. NOT Lua-bound - this is the transparent runtime decrypt hook shared by LuaEngine::RunFile, LuaJsonApi::LoadJson, and LuaFileSystemApi::DoFile (see docs/content-encryption- plan.md, checkpoint 3), each calling this directly on whatever raw bytes SunLight::FileSystem::ReadFile() returns, before treating them as Lua source/JSON text - so a packed (encrypted) bundle and a loose, unencrypted one both just work, with no caller needing to know which it got ahead of time.
 

Detailed Description

Content encryption - protects a game's own .zip bundle content so only that game's own privately-built scarab executable can read it back. See the root README.md's own "Content encryption" section and tools/README.md for the full design/workflow.

Encrypts/decrypts arbitrary binary data using SCARAB_CONTENT_KEY - a shared secret compiled into this specific build of scarab (a CMake option, never a Lua value), the same way SCARAB_VERSION is. Neither primitive here ever takes a key argument, and the key itself is never exposed to Lua as a readable value - every game's own privately-built scarab has it's own key, and only that same build can decrypt what it encrypted. This is deterrence, not unbreakable DRM - see the root README.md's own "Content encryption" section for why that distinction matters.

Key configuration

Set at build time, never at runtime:

cmake -B build -S . -DSCARAB_CONTENT_KEY=<64 hex characters>

A 64-character hex string decodes to the 32 raw bytes crypto_secretbox's key requires. Left empty by default — both primitives above fail cleanly (return nil, log a clear error) rather than silently falling back to some fixed, publicly-known placeholder key. Never commit a real key to version control; pass it from a CI secret or a local, gitignored file instead.

Member Function Documentation

◆ Register()

void Scarab::Engine::Lua::LuaCryptoApi::Register ( lua_State *  pLuaState)
static

Register the content-encryption Lua-callable functions. sodium_init() is called once here rather than lazily inside EncryptData/DecryptData - Register() itself already only ever runs once, at engine startup, matching every other Lua*Api's own one-time setup (e.g. RaylibEngine's constructor registering it's own raylib callback once). libsodium's own docs describe sodium_init() as safe to call more than once regardless, so this isn't strictly required for correctness - just the more explicit, "set up once at startup" shape this codebase already follows elsewhere.

◆ TryDecryptBytes()

bool Scarab::Engine::Lua::LuaCryptoApi::TryDecryptBytes ( const std ::vector< unsigned char > &  data,
std ::vector< unsigned char > &  out 
)
static

Attempt to decrypt a buffer that may have been produced by crypto_encrypt_data/tools/pack.lua, using this build's own SCARAB_CONTENT_KEY. NOT Lua-bound - this is the transparent runtime decrypt hook shared by LuaEngine::RunFile, LuaJsonApi::LoadJson, and LuaFileSystemApi::DoFile (see docs/content-encryption- plan.md, checkpoint 3), each calling this directly on whatever raw bytes SunLight::FileSystem::ReadFile() returns, before treating them as Lua source/JSON text - so a packed (encrypted) bundle and a loose, unencrypted one both just work, with no caller needing to know which it got ahead of time.

See this method's own declaration (luacryptoapi.h) for the full rationale - the transparent runtime decrypt hook shared by LuaEngine::RunFile/LuaJsonApi::LoadJson/ LuaFileSystemApi::DoFile.

Parameters
dataThe raw bytes read from disk - may be plaintext (an unencrypted game, or this build has no key configured at all) or a genuine crypto_encrypt_data-produced blob.
outReceives the decrypted bytes on success; left untouched on failure.
Returns
true if data was successfully decrypted (this build has a valid key AND data authenticates against it) - false otherwise. False is the normal, expected outcome for plaintext content, not an error condition; callers should silently fall back to treating data as plaintext rather than logging anything (unlike crypto_decrypt_data itself, which DOES log - a Lua caller invoking it directly is always expecting encrypted input). A blob encrypted for a DIFFERENT key also returns false here (indistinguishable from plaintext, by design - see AEAD's own guarantee) - the caller then treats the still-encrypted bytes as plaintext, surfacing as an ordinary Lua/JSON parse error rather than a dedicated "wrong key" message.

The documentation for this class was generated from the following files: