Some checks failed
CI / lint (push) Successful in 1m37s
CI / test-python (push) Successful in 1m49s
CI / test-zig (push) Successful in 1m39s
CI / test-wasm (push) Successful in 1m54s
CI / test (push) Successful in 14m44s
CI / miri (push) Successful in 14m18s
CI / build (push) Successful in 1m9s
CI / fuzz-regression (push) Successful in 9m9s
CI / publish (push) Failing after 1m10s
CI / publish-python (push) Failing after 1m46s
CI / publish-wasm (push) Has been cancelled
Signed-off-by: Kamal Tufekcic <kamal@lo.sh>
138 lines
3.7 KiB
Markdown
138 lines
3.7 KiB
Markdown
# 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.0.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.).
|
|
|
|
## Documentation
|
|
|
|
- [Specification.md](https://git.lo.sh/lo/libsoliton/src/branch/main/Specification.md) — full cryptographic specification
|
|
- [CHEATSHEET.md](https://git.lo.sh/lo/libsoliton/src/branch/main/CHEATSHEET.md) — API quick reference
|
|
- [Abstract.md](https://git.lo.sh/lo/libsoliton/src/branch/main/Abstract.md) — formal security model
|
|
|
|
## License
|
|
|
|
[AGPL-3.0-only](LICENSE.md)
|