Skip to content

feat: add X25519 multikey key-agreement keypairs#36

Closed
Peeja wants to merge 3 commits into
mainfrom
claude/fil-475-s7tvfc
Closed

feat: add X25519 multikey key-agreement keypairs#36
Peeja wants to merge 3 commits into
mainfrom
claude/fil-475-s7tvfc

Conversation

@Peeja

@Peeja Peeja commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Adds multikey/x25519: an X25519 keypair type for ECDH key agreement (e.g. ECDH-ES+A256KW key wrapping in the FilOne encryption design).

Unlike the ed25519/secp256k1 signing keys, X25519 keys cannot sign or verify, so this is an independent keypair type rather than a multikey.Signer/multikey.Verifier. It still follows the same multiformats and did:key conventions:

  • tagged private (x25519-priv, 0x1302) / public (x25519-pub, 0xec) bytes, via the shared internal/multiformat helpers
  • Raw/Bytes/Parse/Decode round-trips, plus did:key (z6LS…) encoding and ParsePublicKeyDID for recovering a public key from its DID
  • ECDH shared-secret derivation against a peer public key

Tests cover key generation, the private/public round-trips, wrong-key-type rejection, the did:key prefix/round-trip, and that two parties (and a key recovered from its DID) derive the same ECDH secret.

This is groundwork for the Hilt per-tenant wrap-key registry — FIL-475.

🤖 Generated with Claude Code


Generated by Claude Code

Adds multikey/x25519: an X25519 keypair type for ECDH key agreement
(e.g. ECDH-ES+A256KW key wrapping). Unlike the ed25519/secp256k1 signing
keys, X25519 keys cannot sign or verify, so this is an independent keypair
type rather than a multikey.Signer/Verifier. It still follows the same
multiformats and did:key conventions:

* tagged private (x25519-priv, 0x1302) / public (x25519-pub, 0xec) bytes
* Raw/Bytes/Parse/Decode round-trips, plus did:key (z6LS...) encoding and
  ParsePublicKeyDID for recovering a public key from its DID
* ECDH shared-secret derivation against a peer public key

Groundwork for the Hilt per-tenant wrap-key registry (FIL-475).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7WcBfhKfPFyj2Gp4H6s7R

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new multikey/x25519 package that implements X25519 key-agreement keypairs (ECDH) using the same multiformats + did:key encoding conventions used elsewhere in the multikey family, along with tests validating round-trips and shared-secret derivation.

Changes:

  • Introduces KeyPair and PublicKey types for X25519, including multicodec tagging, multibase encoding/decoding, and did:key round-tripping.
  • Adds ECDH shared-secret derivation between a private keypair and a peer public key.
  • Adds tests covering generation, private/public encode/decode/parse, DID round-trips, wrong-key-type rejection, and ECDH agreement.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
multikey/x25519/x25519.go Implements X25519 keypair/public-key types with multiformats tagging, multibase encoding, did:key support, and ECDH.
multikey/x25519/x25519_test.go Exercises key generation, round-trips (raw/tagged/multibase/DID), rejection cases, and shared-secret agreement.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread multikey/x25519/x25519.go
claude added 2 commits July 3, 2026 15:38
Guard KeyPair.ECDH against a nil *PublicKey (or one with a nil underlying
key) rather than dereferencing it and panicking, since peer keys may come
from external input. Addresses PR review feedback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7WcBfhKfPFyj2Gp4H6s7R
Extend the ECDH nil-guard to the receiver: a nil *KeyPair or a zero-value
keypair (nil underlying private key) now returns an error instead of
panicking, matching the guard already applied to the peer key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7WcBfhKfPFyj2Gp4H6s7R

Peeja commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Closing — X25519 doesn't belong in ucantone after all.

X25519 is a key-agreement key, not a signing key: it's no ucan.Signer/Verifier and has no UCAN role, so it never registers as a multikey decoder and there's nothing UCAN-specific about it. The only consumer is the Hilt tenant wrap-key registry (and, downstream, Ingot's FEE recipient parser) — neither of which is a UCAN concern. This is parallel to what FIL-547 is doing in Ingot, not a ucantone primitive.

So the helper has moved to a hilt-local package, pkg/wrapkey (fil-forge/hilt#14) — keygen, vault custody encoding, and the did:key/Multikey public-key encoding Hilt publishes. The heavy ECDH wrap/unwrap crypto stays in Ingot's fee tree. The one thing the two sides share is the did:key/Multikey wire format (x25519-pub multicodec 0xec + base58btc); rather than couple them through a library, each implements it independently against the standard and Hilt pins it with an anti-drift test vector (RFC 7748 §6.1). Hilt's go.mod stays on main's ucantone pin — no bump needed.

Superseded by fil-forge/hilt#14.


Generated by Claude Code

@Peeja Peeja closed this Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants