Skip to content

crypto,all: allow to choose which crypto key algo are allowed#46

Open
MichaelMure wants to merge 2 commits into
masterfrom
crypto-selection
Open

crypto,all: allow to choose which crypto key algo are allowed#46
MichaelMure wants to merge 2 commits into
masterfrom
crypto-selection

Conversation

@MichaelMure

@MichaelMure MichaelMure commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Note

Medium Risk
Changes default key decoding (empty DefaultKeySet without crypto/all), RSA multibase wire format, and when did:key rejects keys—callers must register algorithms explicitly; wrong migration breaks resolution and interoperability with existing RSA multibase expectations.

Overview
Replaces the monolithic crypto/_allkeys decoder with a pluggable KeySet / KeyType model so callers choose which algorithms (and RSA modulus sizes) are accepted. DefaultKeySet starts empty; register via crypto.Register(...) or blank-import crypto/all for the old “accept everything” behavior in tests/tools.

DID resolution gains did.WithKeySet(...), wired through did:key, did:plc, and Multikey decoding so document resolution fails when the embedded key’s algorithm is outside policy. did:key no longer decodes the public key at parse time—only when building the document.

Each crypto/<algo> package exports KeyType() and WrapPublicKey for stdlib/native key types. RSA publicKeyMultibase encoding switches to PKCS#1 DER (encode/decode), with optional size allowlists on rsa.KeyType(2048, ...). Typed errors distinguish ErrKeyNotAccepted vs ErrInvalidKey.

Reviewed by Cursor Bugbot for commit e92e0ca. Bugbot is set up for automated code reviews on this repo. Configure here.

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

This PR refactors public-key decoding to be policy-driven via a pluggable crypto.KeySet, allowing callers to control which key algorithms (and for RSA, modulus sizes) are permitted during DID resolution. It replaces the previous “decode everything” approach (crypto/_allkeys) with opt-in registration (including a crypto/all convenience package) and wires the policy into did:key and did:plc resolution paths.

Changes:

  • Introduces crypto.KeySet/crypto.KeyType, an initially-empty crypto.DefaultKeySet, and a crypto/all side-effect import to register all supported algorithms.
  • Adds did.WithKeySet(...) and updates did:key + did:plc resolution to decode public keys through the selected key set (moving did:key validation from parse-time to Document()).
  • Switches RSA publicKeyMultibase encoding/decoding to PKCS#1 RSAPublicKey DER (from prior PKIX/X.509 encoding).

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
verifiers/did-web/web.go Documents that did:web does not apply WithKeySet during resolution.
verifiers/did-plc/plc.go Decodes did:plc embedded did:key public keys via the resolution KeySet.
verifiers/did-plc/plc_test.go Updates tests to opt into all algorithms via crypto/all.
verifiers/did-plc/document_test.go Adds coverage verifying WithKeySet enforcement during did:plc resolution.
verifiers/did-key/key.go Defers key decoding to Document() using the resolution KeySet; parse no longer decodes/validates keys.
verifiers/did-key/key_test.go Updates tests for new did:key behavior and adds WithKeySet coverage.
verifiers/_methods/multikey/multikey.go Switches Multikey JSON decoding to use crypto.PublicKeyFromMultibase (DefaultKeySet-governed).
options.go Adds ResolutionOpts.keySet, accessor KeySet(), and did.WithKeySet(...).
document/document_test.go Ensures tests register algorithms via crypto/all.
did_test.go Adds WithKeySet tests and registers algorithms via crypto/all.
crypto/x25519/key.go Adds x25519.KeyType() for KeySet registration.
crypto/secp256k1/key.go Adds secp256k1.KeyType() for KeySet registration.
crypto/rsa/public.go Changes RSA multibase decode/encode to PKCS#1 RSAPublicKey DER.
crypto/rsa/key.go Adds rsa.KeyType(sizes...) to encode RSA size policy into a KeySet.
crypto/p521/key.go Adds p521.KeyType() for KeySet registration.
crypto/p384/key.go Adds p384.KeyType() for KeySet registration.
crypto/p256/key.go Adds p256.KeyType() for KeySet registration.
crypto/keyset.go Introduces KeySet, KeyType, DefaultKeySet, and helper decode APIs.
crypto/keyset_test.go Adds tests for algorithm restriction and RSA size policy enforcement.
crypto/ed25519/key.go Adds ed25519.KeyType() for KeySet registration.
crypto/all/all.go Adds a kitchen-sink side-effect import to register all algorithms into DefaultKeySet.
crypto/_allkeys/allkeys.go Removes the previous monolithic “all algorithms” decoder.

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

Comment thread options.go
Comment on lines +65 to +68
// WithKeySet provides a KeySet, a set of cryptographic key algorithm as
// allowed during resolution. If the DID to resolve has an algorithm not included
// in this set, resolution will fail.
// This is a way for the caller to control what algorithm are deemed safe or expected.
Comment thread crypto/keyset.go
Comment on lines +17 to +19
// The decode functions return a nil PublicKey/PrivateKey together with an error on failure; a nil
// function means that form is not supported for this algorithm (for example RSA has no raw private
// bytes form).
Comment thread verifiers/did-web/web.go
return "web"
}

// Does not support WithKeySet.
Comment thread verifiers/did-plc/document_test.go
}

m.pubkey, err = allkeys.PublicKeyFromPublicKeyMultibase(aux.PublicKeyMultibase)
m.pubkey, err = crypto.PublicKeyFromMultibase(aux.PublicKeyMultibase)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Multikey ignores KeySet policy

Medium Severity

Multikey JSON unmarshaling still calls crypto.PublicKeyFromMultibase, which always uses DefaultKeySet. WithKeySet on DID resolution only affects paths like did:key and did:plc, so a restricted resolution policy can be bypassed when verification methods are loaded from JSON via Multikey.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b6ba90a. Configure here.

dovydas55
dovydas55 previously approved these changes Jun 26, 2026

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e92e0ca. Configure here.

Comment thread crypto/keyset.go
}
if err != nil {
return nil, err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WrapPublicKey omits ErrInvalidKey

Medium Severity

KeySet.WrapPublicKey returns algorithm validation errors unchanged, while PublicKeyFromBytes wraps the same failures with ErrInvalidKey (unless they are ErrKeyNotAccepted). Callers using errors.Is to tell malformed keys from policy rejections get inconsistent results depending on which API they use.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e92e0ca. Configure here.

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