mirror of
https://github.com/zap-proto/go.git
synced 2026-10-30 15:05:00 +00:00
zapgen — interface (RPC) support: - Parse `interface` decls (brace + whitespace forms, one parser) with 1-based auto-assigned method ordinals; methods take ≤1 struct request and (after `returns`) ≤1 struct response, matching the spec README grammar. - desugar: `interface` opens a whitespace block; method lines pass through verbatim (no @N). Block headers now honored only at file scope, so a struct field NAMED `interface`/`struct` stays a field (H4 preserved). - emit: per interface a 1-based ordinal table, a typed Client over a Channel seam, and an abstract Handler + Dispatch<Iface> ordinal router, all over the new runtime call envelope. Method names exported. - New `rpc` package: the ZAP call envelope (BuildRequest/ParseRequest, BuildResponse/ParseResponse, Call, Response, status codes), byte-compatible with the other runtimes' transport envelopes (Version2 header + router msgType flags). Adds zap.NewBuilderV2. - examples/echo: generated service + end-to-end client↔dispatch↔handler test covering request/response, void, no-request, bare, handler-error, and unknown-ordinal paths. Golden fixtures for the interface codegen. cap — reconcile to SPEC v1.1: - B3 signature scope: sign SPEC §3 canonical bytes (Capability[0..164) || canonical(Caveats), Kind:u32||len:u32||Value), via Cap.CanonicalBytes — one definition shared by signer and verifier; excludes Sig and heap indirection so caps verify cross-language. CapID = Hash32(Canonical||Sig). - B2 delegation gate: define cross-cutting Permission bits (PermAttenuate 1<<32, PermAudit, PermRoot); enforce SPEC §2.3 step 3d in VerifyChain and at mint time in Attenuate (refuse a cap the verifier would reject). - B4/B6: VerifyRevocation is scheme-aware (dispatches on the tag byte); verifySig fails closed on SchemeReserved/unknown instead of falling back to ed25519. Verifier.VerifyRevocation added for PQ revocations. - spec_test.go covers all four. Rebrand finish + docs: - Zero capnp/Cap'n Proto and zero hanzo/avalabs/capnproto.org tokens in zap-native source (zap.go doc neutralized; cap doc-comment brand refs generalized). LLM.md refreshed: zapgen shipped (not "forthcoming"), rpc package, interface DSL, cap signature scope. Ignore the agents example binary. go build ./... and go test ./... -count=1 pass; race-clean on changed pkgs.
97 lines
3.5 KiB
Go
97 lines
3.5 KiB
Go
// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package cap
|
|
|
|
import (
|
|
"crypto/ed25519"
|
|
"crypto/rand"
|
|
"errors"
|
|
)
|
|
|
|
// Signer abstracts the issuer's signing key. The v1.1 wire format's
|
|
// signature footer (SigSize bytes, see cap.go) is wide enough for any
|
|
// supported primitive: secp256k1 ECDSA (65 B), Ed25519 (64 B), or
|
|
// ML-DSA-65 (3309 B per FIPS 204 §5.2). Implementations write their
|
|
// scheme tag at sig[AlgTagOffset] before signing so verifiers can
|
|
// dispatch on it.
|
|
//
|
|
// This package only requires the interface; concrete signers live in a
|
|
// consumer's auth layer where the appropriate crypto dependency is wired
|
|
// in. The Ed25519Signer stub below is provided for tests and bootstrap.
|
|
type Signer interface {
|
|
// Sign returns a fixed-size signature over the supplied payload.
|
|
// The signature MUST verify under the Public() key on the verifier
|
|
// side. Implementations SHOULD be deterministic per call for
|
|
// replay-debugging and MUST NOT leak the secret key. The final
|
|
// byte (sig[AlgTagOffset]) MUST carry the algorithm tag.
|
|
Sign(payload []byte) ([SigSize]byte, error)
|
|
|
|
// Public returns the canonical 32-byte hash of the signer's public
|
|
// key. This must match the cap's Issuer field for Verify to accept
|
|
// the signature.
|
|
Public() [32]byte
|
|
}
|
|
|
|
// ---- ed25519 test stub ----------------------------------------------------
|
|
|
|
// Ed25519Signer is a Signer backed by an ed25519 key. ed25519's native
|
|
// signature is 64 bytes; this stub places it at the leading bytes of
|
|
// the SigSize footer with the remaining bytes zero-padded and the
|
|
// algorithm tag (SchemeEd25519 = 0x02) at sig[AlgTagOffset]. The
|
|
// matching verifier (verifyEd25519) reads the leading 64 bytes back
|
|
// out and ignores the pad and tag byte.
|
|
//
|
|
// This is intended for tests and bootstrap. Production PQ deployments
|
|
// plug an ML-DSA-65 Signer via a consumer's auth layer.
|
|
type Ed25519Signer struct {
|
|
priv ed25519.PrivateKey
|
|
pub [32]byte
|
|
}
|
|
|
|
// NewEd25519Signer generates a fresh keypair.
|
|
func NewEd25519Signer() (*Ed25519Signer, error) {
|
|
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s := &Ed25519Signer{priv: priv}
|
|
s.pub = Hash32(pub)
|
|
return s, nil
|
|
}
|
|
|
|
// Sign produces a 64-byte ed25519 signature placed at the leading bytes
|
|
// of the SigSize footer and tagged with SchemeEd25519 at AlgTagOffset.
|
|
func (s *Ed25519Signer) Sign(payload []byte) ([SigSize]byte, error) {
|
|
var out [SigSize]byte
|
|
sig := ed25519.Sign(s.priv, payload)
|
|
if len(sig) != ed25519.SignatureSize {
|
|
return out, errors.New("cap: ed25519 sign produced wrong size")
|
|
}
|
|
copy(out[:ed25519.SignatureSize], sig)
|
|
out[AlgTagOffset] = byte(SchemeEd25519)
|
|
return out, nil
|
|
}
|
|
|
|
// Public returns the 32-byte hash of the ed25519 public key.
|
|
func (s *Ed25519Signer) Public() [32]byte { return s.pub }
|
|
|
|
// PublicKey returns the raw 32-byte ed25519 public key. Used in tests to
|
|
// register the signer with a Verifier's IssuerKey lookup.
|
|
func (s *Ed25519Signer) PublicKey() ed25519.PublicKey {
|
|
return s.priv.Public().(ed25519.PublicKey)
|
|
}
|
|
|
|
// verifyEd25519 checks a padded ed25519 signature against a raw pubkey.
|
|
// The signature occupies sig[:ed25519.SignatureSize]; the bytes between
|
|
// it and sig[AlgTagOffset] are zero pad ignored by this verifier.
|
|
func verifyEd25519(pub []byte, payload []byte, sig [SigSize]byte) error {
|
|
if len(pub) != ed25519.PublicKeySize {
|
|
return errors.New("cap: ed25519 pubkey wrong size")
|
|
}
|
|
if !ed25519.Verify(ed25519.PublicKey(pub), payload, sig[:ed25519.SignatureSize]) {
|
|
return ErrSigMismatch
|
|
}
|
|
return nil
|
|
}
|