Feature-gaps surfaced by the cross-ecosystem crypto-DRY assessment (docs/CRYPTO_DRY_ASSESSMENT.md). These are the verify-side features downstreams had to hand-roll because verify doesn't expose them — deferred out of the v10.4.0 correctness cut because each needs API/wire design with its consumer.
1. Raw Ed25519 / P-256 verify on the FFI + wheel
The wheel exposes sign_ed25519 but no verify counterpart, so a Python consumer that signs through verify can't round-trip verification through verify (CIRISAgent audit/signing_protocol.py falls back to the cryptography library). Add ciris_verify_verify_ed25519 / ciris_verify_verify_p256 + wheel bindings. Low severity (RFC 8032 verify has ~zero drift risk) but closes the asymmetry.
2. secp256k1 tx-fields signing on the FFI (funds-moving)
ciris_verify_sign_evm_transaction takes only a pre-computed 32-byte hash, so CIRISAgent rebuilds RLP + keccak256 (with a 3-way third-party fallback: pysha3→pycryptodome→eth_hash) + EIP-155 v + EIP-55 checksum + ERC-4337 userOp hashing in Python, for real-money txs. secp256k1.rs already has keccak256 + EIP-155 internally. Expose: a tx-fields entrypoint (RLP+keccak inside the boundary), keccak256, and checksum-arbitrary-address. Medium.
3. doc_integrity on the wheel
Rust-only today, so the agent can't produce hybrid, domain-separated, version-bound verifiable-claim receipts — its DSAR deletion "proofs" use self-minted ephemeral RSA-2048 instead. Expose a produce-hybrid-signed-receipt surface on the FFI/wheel. Medium.
4. Async bound-hybrid sign/verify composer
The pqc = Sign_PQC(data ‖ ed_sig) binding rule is hand-recomposed in ~7 downstream sites (persist signing/mod.rs, edge identity.rs/capacity.rs, server lens-core ×3) — and the KMP FederationSigner.kt got it wrong (signs body, not body‖ed_sig). self_at_login::SelfSigner::sign_bound exists but is producer-shaped (returns base64 strings, no pubkeys/algo tags). Expose a general async helper that produces a full HybridSignature over ciris-keyring's async signers, so callers stop re-deriving the binding. Medium.
5. ALM §19.4 SignedRelayCapacity preimage — pick one layout
Edge's production SignedRelayCapacity and verify's holonomic::alm::signing_preimage share the domain CIRISALM-CAPv2\0\0 but have completely incompatible byte layouts (f32 vs u32 uplink, raw vs length-prefixed peer_id, edge includes stream_id/commitments). Verify's §19.4 verifier is dead against real edge traffic, and ALM is absent from the §19 cross-impl vector set (which is why it was never caught). Decide the authoritative layout (edge's v2 is the producer), regenerate verify's preimage to match or bump to CAPv3, and add the missing ALM golden to the vector set. High (domain-separation break + dead PIN-normative gate).
6. keyring seal-mints bypass the SP 800-90B latch (verify self-gap)
ciris-keyring's own mints (sealed_ed25519.rs:87, sealed_mldsa65.rs:125, usb_wrapped_mldsa65.rs, transport_identity.rs, software.rs) draw raw OsRng, so the #74 "no weak key is ever produced" invariant only holds for ciris-crypto-constructed keys, not keyring-sealed ones. Route them through ciris_crypto::random::fill. Low.
Assessment doc (this repo): docs/CRYPTO_DRY_ASSESSMENT.md → "Gaps-in-verify roadmap".
Feature-gaps surfaced by the cross-ecosystem crypto-DRY assessment (
docs/CRYPTO_DRY_ASSESSMENT.md). These are the verify-side features downstreams had to hand-roll because verify doesn't expose them — deferred out of the v10.4.0 correctness cut because each needs API/wire design with its consumer.1. Raw Ed25519 / P-256 verify on the FFI + wheel
The wheel exposes
sign_ed25519but no verify counterpart, so a Python consumer that signs through verify can't round-trip verification through verify (CIRISAgentaudit/signing_protocol.pyfalls back to thecryptographylibrary). Addciris_verify_verify_ed25519/ciris_verify_verify_p256+ wheel bindings. Low severity (RFC 8032 verify has ~zero drift risk) but closes the asymmetry.2. secp256k1 tx-fields signing on the FFI (funds-moving)
ciris_verify_sign_evm_transactiontakes only a pre-computed 32-byte hash, so CIRISAgent rebuilds RLP + keccak256 (with a 3-way third-party fallback: pysha3→pycryptodome→eth_hash) + EIP-155 v + EIP-55 checksum + ERC-4337 userOp hashing in Python, for real-money txs.secp256k1.rsalready has keccak256 + EIP-155 internally. Expose: a tx-fields entrypoint (RLP+keccak inside the boundary),keccak256, and checksum-arbitrary-address. Medium.3.
doc_integrityon the wheelRust-only today, so the agent can't produce hybrid, domain-separated, version-bound verifiable-claim receipts — its DSAR deletion "proofs" use self-minted ephemeral RSA-2048 instead. Expose a produce-hybrid-signed-receipt surface on the FFI/wheel. Medium.
4. Async bound-hybrid sign/verify composer
The
pqc = Sign_PQC(data ‖ ed_sig)binding rule is hand-recomposed in ~7 downstream sites (persistsigning/mod.rs, edgeidentity.rs/capacity.rs, server lens-core ×3) — and the KMPFederationSigner.ktgot it wrong (signsbody, notbody‖ed_sig).self_at_login::SelfSigner::sign_boundexists but is producer-shaped (returns base64 strings, no pubkeys/algo tags). Expose a general async helper that produces a fullHybridSignatureoverciris-keyring's async signers, so callers stop re-deriving the binding. Medium.5. ALM §19.4
SignedRelayCapacitypreimage — pick one layoutEdge's production
SignedRelayCapacityand verify'sholonomic::alm::signing_preimageshare the domainCIRISALM-CAPv2\0\0but have completely incompatible byte layouts (f32 vs u32 uplink, raw vs length-prefixed peer_id, edge includes stream_id/commitments). Verify's §19.4 verifier is dead against real edge traffic, and ALM is absent from the §19 cross-impl vector set (which is why it was never caught). Decide the authoritative layout (edge's v2 is the producer), regenerate verify's preimage to match or bump toCAPv3, and add the missing ALM golden to the vector set. High (domain-separation break + dead PIN-normative gate).6. keyring seal-mints bypass the SP 800-90B latch (verify self-gap)
ciris-keyring's own mints (sealed_ed25519.rs:87,sealed_mldsa65.rs:125,usb_wrapped_mldsa65.rs,transport_identity.rs,software.rs) draw rawOsRng, so the #74 "no weak key is ever produced" invariant only holds forciris-crypto-constructed keys, not keyring-sealed ones. Route them throughciris_crypto::random::fill. Low.Assessment doc (this repo):
docs/CRYPTO_DRY_ASSESSMENT.md→ "Gaps-in-verify roadmap".