add zig 0.15 crypto and testing notes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Changed files
+64 -1
languages
+2
languages/ziglang/0.15/README.md
··· 9 9 - [build](./build.md) - createModule + imports, hash trick 10 10 - [comptime](./comptime.md) - type generation, tuple synthesis, validation 11 11 - [concurrency](./concurrency.md) - atomics vs mutex, callback pattern 12 + - [crypto](./crypto.md) - ecdsa paths, signature verification 13 + - [testing](./testing.md) - zig test vs build test, arena for leaky apis
+44
languages/ziglang/0.15/crypto.md
··· 1 + # crypto 2 + 3 + zig 0.15 crypto paths and patterns. 4 + 5 + ## ecdsa 6 + 7 + the ecdsa types are under `std.crypto.sign.ecdsa`, not `std.crypto.ecdsa`: 8 + 9 + ```zig 10 + const crypto = std.crypto; 11 + 12 + // correct (0.15) 13 + const Secp256k1 = crypto.sign.ecdsa.EcdsaSecp256k1Sha256; 14 + const P256 = crypto.sign.ecdsa.EcdsaP256Sha256; 15 + 16 + // wrong - will error "has no member named 'ecdsa'" 17 + // const Secp256k1 = crypto.ecdsa.EcdsaSecp256k1Sha256; 18 + ``` 19 + 20 + ## verifying signatures 21 + 22 + ```zig 23 + const Scheme = std.crypto.sign.ecdsa.EcdsaSecp256k1Sha256; 24 + 25 + // signature is r || s (64 bytes for 256-bit curves) 26 + const sig = Scheme.Signature.fromBytes(sig_bytes[0..64].*); 27 + 28 + // public key from SEC1 compressed format (33 bytes) 29 + const public_key = try Scheme.PublicKey.fromSec1(key_bytes); 30 + 31 + // verify - returns error.SignatureVerificationFailed on mismatch 32 + try sig.verify(message, public_key); 33 + ``` 34 + 35 + ## key sizes 36 + 37 + | curve | compressed pubkey | uncompressed pubkey | signature (r\|\|s) | 38 + |-------|-------------------|---------------------|-------------------| 39 + | P-256 | 33 bytes | 65 bytes | 64 bytes | 40 + | secp256k1 | 33 bytes | 65 bytes | 64 bytes | 41 + 42 + compressed keys start with 0x02 or 0x03. uncompressed start with 0x04. 43 + 44 + see: [zat/jwt.zig](https://tangled.sh/@zzstoatzz.io/zat/tree/main/src/internal/jwt.zig)
+16
languages/ziglang/0.15/testing.md
··· 1 + # testing 2 + 3 + `zig build test` compiles tests but may not run them if your build.zig doesn't wire it up correctly. to actually run tests: 4 + 5 + ```bash 6 + zig test src/foo.zig # runs tests in foo.zig and its imports 7 + zig test src/foo.zig --test-filter "parse" # only tests matching "parse" 8 + ``` 9 + 10 + the testing allocator catches leaks. if you use `parseFromValueLeaky` or similar "leaky" apis, wrap in an arena: 11 + 12 + ```zig 13 + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); 14 + defer arena.deinit(); 15 + const result = try leakyFunction(arena.allocator(), input); 16 + ```
+2 -1
languages/ziglang/README.md
··· 4 4 5 5 ## topics 6 6 7 - - [0.15](./0.15/) - version-specific patterns (i/o overhaul, arraylist, concurrency) 7 + - [0.15](./0.15/) - version-specific patterns (i/o, arraylist, crypto, testing) 8 8 - [build](./build/) - build system patterns from large projects 9 9 10 10 ## sources ··· 17 17 | [find-bufo](https://tangled.sh/@zzstoatzz.io/find-bufo) | bluesky bot | 18 18 | [leaflet-search](https://tangled.sh/@zzstoatzz.io/leaflet-search) | fts search backend | 19 19 | [zql](https://tangled.sh/@zzstoatzz.io/zql) | comptime sql parsing | 20 + | [zat](https://tangled.sh/@zzstoatzz.io/zat) | atproto primitives (jwt, crypto) | 20 21 | [ghostty](https://github.com/ghostty-org/ghostty) | terminal emulator (build system) | 21 22 | [bun](https://github.com/oven-sh/bun) | javascript runtime (build system) | 22 23