From 62a0cb9d60669dd3f37a050801d54629b960936e Mon Sep 17 00:00:00 2001 From: Derek Miller <1340081+derek-miller@users.noreply.github.com> Date: Mon, 20 Jul 2026 11:46:57 -0500 Subject: [PATCH] Add core + portable builds; core is the canonical crypto.lua The canonical crypto.lua is the CORE build (bitn excluded, expected on the Lua path) so it composes with sibling libraries that share bitn without duplicating it. crypto-portable.lua bundles every dependency for zero-dependency drop-in use. CI/release publish both; the post-build version smoke-test now covers both variants. Also fixes the x25519 usage example (generate_keypair returns two values, not a table). --- .github/workflows/build.yml | 7 +++++++ .github/workflows/release.yml | 1 + CLAUDE.md | 12 +++++++++--- Makefile | 16 ++++++++++------ README.md | 18 +++++++++++------- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cbeee39..9367d6a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -113,6 +113,13 @@ jobs: echo "❌ build/crypto.lua missing" exit 1 fi + # Check portable build (all dependencies bundled) + if [ -f "build/crypto-portable.lua" ]; then + echo "✅ build/crypto-portable.lua exists ($(wc -c < "build/crypto-portable.lua") bytes)" + else + echo "❌ build/crypto-portable.lua missing" + exit 1 + fi - name: Upload artifacts uses: actions/upload-artifact@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4d3103..f4cf9fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,3 +45,4 @@ jobs: generate_release_notes: true files: | build/crypto.lua + build/crypto-portable.lua diff --git a/CLAUDE.md b/CLAUDE.md index 7a86adb..ce703e1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -90,13 +90,19 @@ make test-matrix # across Lua 5.1–5.4 + LuaJIT ## Building -`amalg` produces a single-file distribution from `src/crypto/init.lua`: +`amalg` produces two single-file distributions from `src/crypto/init.lua`: ```bash -make build # Output: build/crypto.lua (bitn bundled in) +make build # Output: build/crypto.lua (core; bitn excluded via `-i bitn`) + # build/crypto-portable.lua (all dependencies bundled) ``` -Version is automatically injected from git tags during release. +`crypto.lua` is the **canonical core build**: it excludes `bitn` and expects it +on the Lua path, so it composes with other libraries that share `bitn` without +duplicating it (e.g. lua-noiseprotocol vendors this as `vendor/crypto.lua` +alongside its own `vendor/bitn.lua`). `crypto-portable.lua` bundles every +dependency for a single drop-in file with zero external requires. Version is +injected from git tags during release. ## CI/CD diff --git a/Makefile b/Makefile index e1cc88f..65ef503 100644 --- a/Makefile +++ b/Makefile @@ -66,19 +66,23 @@ build/amalg.cache: src/crypto/init.lua build: build/amalg.cache @echo "Building single-file distribution..." @if command -v amalg.lua >/dev/null 2>&1; then \ - LUA_PATH="$(LUA_PATH_LOCAL)" amalg.lua -o build/crypto.lua -C ./build/amalg.cache || exit 1;\ - echo "Built build/crypto.lua"; \ + LUA_PATH="$(LUA_PATH_LOCAL)" amalg.lua -o build/crypto.lua -C ./build/amalg.cache -i "bitn" || exit 1;\ + echo "Built build/crypto.lua (core; bitn excluded, expected on the path)"; \ + LUA_PATH="$(LUA_PATH_LOCAL)" amalg.lua -o build/crypto-portable.lua -C ./build/amalg.cache || exit 1; \ + echo "Built build/crypto-portable.lua (portable; all dependencies bundled)"; \ VERSION=$$(git describe --exact-match --tags 2>/dev/null || echo "dev"); \ if [ "$$VERSION" != "dev" ]; then \ echo "Injecting version $$VERSION..."; \ sed -i.bak 's/VERSION = "dev"/VERSION = "'$$VERSION'"/' build/crypto.lua && rm build/crypto.lua.bak; \ + sed -i.bak 's/VERSION = "dev"/VERSION = "'$$VERSION'"/' build/crypto-portable.lua && rm build/crypto-portable.lua.bak; \ fi; \ echo "Testing version function..."; \ - LUA_VERSION=$$(lua -e 'local b = require("build.crypto"); print(b.version())' 2>/dev/null || echo "test failed"); \ - if [ "$$LUA_VERSION" = "$$VERSION" ]; then \ - echo "Version correctly set to: $$VERSION"; \ + CORE_VERSION=$$(LUA_PATH="$(LUA_PATH_LOCAL)" lua -e 'local b = require("build.crypto"); print(b.version())' 2>/dev/null || echo "test failed"); \ + PORTABLE_VERSION=$$(LUA_PATH="$(LUA_PATH_LOCAL)" lua -e 'local b = require("build.crypto-portable"); print(b.version())' 2>/dev/null || echo "test failed"); \ + if [ "$$CORE_VERSION" = "$$VERSION" ] && [ "$$PORTABLE_VERSION" = "$$VERSION" ]; then \ + echo "Version correctly set to: $$VERSION (core + portable)"; \ else \ - echo "Version test failed. Expected: $$VERSION, Got: $$LUA_VERSION"; \ + echo "Version test failed. Expected: $$VERSION, core: $$CORE_VERSION, portable: $$PORTABLE_VERSION"; \ fi; \ else \ echo "Error: amalg not found."; \ diff --git a/README.md b/README.md index 5167051..e381b68 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,12 @@ pure-Lua implementations** regardless of this flag, because the shipped Download a pre-built single-file module from the [Releases](https://github.com/finitelabs/lua-crypto/releases) page: -- **`crypto.lua`** — complete bundle with all dependencies included (zero - external dependencies) +- **`crypto.lua`** — the canonical **core** build. Requires `bitn` + ([lua-bitn](https://github.com/finitelabs/lua-bitn)) on the Lua path. Use this + when composing with other libraries that already provide `bitn`, so the shared + dependency is vendored only once. +- **`crypto-portable.lua`** — **portable** build with every dependency bundled + in (zero external dependencies). Use this when you want a single drop-in file. ### Option 2: From Source @@ -87,11 +91,11 @@ local tag = crypto.sha256.hmac_sha256_hex(key, message) local sealed = crypto.chacha20_poly1305.encrypt(key, nonce, plaintext, aad) local opened = crypto.chacha20_poly1305.decrypt(key, nonce, sealed, aad) --- Diffie-Hellman (X25519) -local alice = crypto.x25519.generate_keypair() -local bob = crypto.x25519.generate_keypair() -local shared_a = crypto.x25519.diffie_hellman(alice.private_key, bob.public_key) -local shared_b = crypto.x25519.diffie_hellman(bob.private_key, alice.public_key) +-- Diffie-Hellman (X25519); generate_keypair() returns private, public +local alice_priv, alice_pub = crypto.x25519.generate_keypair() +local bob_priv, bob_pub = crypto.x25519.generate_keypair() +local shared_a = crypto.x25519.diffie_hellman(alice_priv, bob_pub) +local shared_b = crypto.x25519.diffie_hellman(bob_priv, alice_pub) assert(shared_a == shared_b) ```