···99- [build](./build.md) - createModule + imports, hash trick
1010- [comptime](./comptime.md) - type generation, tuple synthesis, validation
1111- [concurrency](./concurrency.md) - atomics vs mutex, callback pattern
1212+- [crypto](./crypto.md) - ecdsa paths, signature verification
1313+- [testing](./testing.md) - zig test vs build test, arena for leaky apis
+44
languages/ziglang/0.15/crypto.md
···11+# crypto
22+33+zig 0.15 crypto paths and patterns.
44+55+## ecdsa
66+77+the ecdsa types are under `std.crypto.sign.ecdsa`, not `std.crypto.ecdsa`:
88+99+```zig
1010+const crypto = std.crypto;
1111+1212+// correct (0.15)
1313+const Secp256k1 = crypto.sign.ecdsa.EcdsaSecp256k1Sha256;
1414+const P256 = crypto.sign.ecdsa.EcdsaP256Sha256;
1515+1616+// wrong - will error "has no member named 'ecdsa'"
1717+// const Secp256k1 = crypto.ecdsa.EcdsaSecp256k1Sha256;
1818+```
1919+2020+## verifying signatures
2121+2222+```zig
2323+const Scheme = std.crypto.sign.ecdsa.EcdsaSecp256k1Sha256;
2424+2525+// signature is r || s (64 bytes for 256-bit curves)
2626+const sig = Scheme.Signature.fromBytes(sig_bytes[0..64].*);
2727+2828+// public key from SEC1 compressed format (33 bytes)
2929+const public_key = try Scheme.PublicKey.fromSec1(key_bytes);
3030+3131+// verify - returns error.SignatureVerificationFailed on mismatch
3232+try sig.verify(message, public_key);
3333+```
3434+3535+## key sizes
3636+3737+| curve | compressed pubkey | uncompressed pubkey | signature (r\|\|s) |
3838+|-------|-------------------|---------------------|-------------------|
3939+| P-256 | 33 bytes | 65 bytes | 64 bytes |
4040+| secp256k1 | 33 bytes | 65 bytes | 64 bytes |
4141+4242+compressed keys start with 0x02 or 0x03. uncompressed start with 0x04.
4343+4444+see: [zat/jwt.zig](https://tangled.sh/@zzstoatzz.io/zat/tree/main/src/internal/jwt.zig)
+16
languages/ziglang/0.15/testing.md
···11+# testing
22+33+`zig build test` compiles tests but may not run them if your build.zig doesn't wire it up correctly. to actually run tests:
44+55+```bash
66+zig test src/foo.zig # runs tests in foo.zig and its imports
77+zig test src/foo.zig --test-filter "parse" # only tests matching "parse"
88+```
99+1010+the testing allocator catches leaks. if you use `parseFromValueLeaky` or similar "leaky" apis, wrap in an arena:
1111+1212+```zig
1313+var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
1414+defer arena.deinit();
1515+const result = try leakyFunction(arena.allocator(), input);
1616+```