# soliton-zig Zig wrapper for [libsoliton](https://git.lo.sh/lo/libsoliton) — a pure-Rust post-quantum cryptographic library. Consumes the C ABI via `@cImport`. ## Build Requires `libsoliton_capi` built from the workspace: ```bash # From the workspace root cargo build --release -p libsoliton_capi # Run Zig tests cd soliton_zig zig build test ``` The build script links against `../target/release/libsoliton_capi.so` and includes the header from `../soliton_capi/soliton.h`. ## Usage Add as a Zig dependency in `build.zig.zon`: ```zig .dependencies = .{ .soliton = .{ .url = "https://git.lo.sh/lo/libsoliton/archive/v0.1.1.tar.gz", .hash = "...", }, }, ``` ```zig const soliton = @import("soliton"); // Identity var id = try soliton.Identity.generate(); defer id.deinit(); var fp: [32]u8 = undefined; try id.fingerprint(&fp); var sig = try id.sign("hello"); defer sig.deinit(); try id.verify("hello", sig.slice()); // Auth var challenge = try soliton.authChallenge(&id.public_key); defer challenge.ct.deinit(); var proof: [32]u8 = undefined; try soliton.authRespond(&id.secret_key, challenge.ct.slice(), &proof); assert(soliton.authVerify(&challenge.token, &proof)); // Primitives var hash: [32]u8 = undefined; try soliton.sha3_256("abc", &hash); var tag: [32]u8 = undefined; try soliton.hmacSha3_256(key, data, &tag); var okm: [64]u8 = undefined; try soliton.hkdfSha3_256(salt, ikm, info, &okm); // AEAD var ct = try soliton.aeadEncrypt(&key, &nonce, plaintext, aad); defer ct.deinit(); var pt = try soliton.aeadDecrypt(&key, &nonce, ct.slice(), aad); defer pt.deinit(); // X-Wing var kp = try soliton.xwingKeygen(); defer kp.deinit(); // KEX var spk_sig = try soliton.kexSignPrekey(&bob.secret_key, &spk.pk); defer spk_sig.deinit(); var initiated = try soliton.kexInitiate(...); defer initiated.deinit(); var received = try soliton.kexReceive(...); defer received.deinit(); // Ratchet var alice_r = try soliton.Ratchet.initAlice(root_key, chain_key, ...); defer alice_r.deinit(); var msg = try alice_r.encrypt("hello"); defer msg.deinit(); // Serialize var result = try alice_r.toBytes(); defer result.blob.deinit(); // result.epoch for anti-rollback storage // Storage var ring = try soliton.KeyRing.init(&key, 1); defer ring.deinit(); var blob = try ring.encryptBlob("channel", "segment", plaintext); defer blob.deinit(); // Streaming AEAD var enc = try soliton.StreamEncryptor.init(&key, null, false); defer enc.deinit(); var hdr: [soliton.STREAM_HEADER_SIZE]u8 = undefined; try enc.header(&hdr); const written = try enc.encryptChunk(data, true, &out_buf); // Call Keys var keys = try alice_r.deriveCallKeys(&kem_ss, &call_id); defer keys.deinit(); var send: [32]u8 = undefined; try keys.sendKey(&send); // Verification var phrase = try soliton.verificationPhrase(&pk_a, &pk_b); defer phrase.deinit(); // Argon2id try soliton.argon2id(password, &salt, 65536, 3, 4, &out); ``` ## API All functions return `Error!T` where `Error` maps 1:1 to the CAPI error codes. Opaque types (`Identity`, `Ratchet`, `KeyRing`, `StreamEncryptor`, `StreamDecryptor`, `CallKeys`, `XWingKeyPair`) must be `deinit()`'d for cleanup and zeroization. `Buf` wraps library-allocated buffers and is freed via `deinit()`. All constants from `soliton.h` are re-exported (`PUBLIC_KEY_SIZE`, `SECRET_KEY_SIZE`, `XWING_PK_SIZE`, etc.).