Skip to content

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

Open
MichaelMure wants to merge 1 commit into
masterfrom
crypto-selection
Open

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

Conversation

@MichaelMure

@MichaelMure MichaelMure commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Note

High Risk
Changes cryptographic acceptance policy and default behavior (empty DefaultKeySet), alters when did:key keys are validated, and fixes RSA multibase wire format—callers may break or see interoperability shifts until they register algorithms or pass WithKeySet.

Overview
Replaces the monolithic crypto/_allkeys decoder with a KeySet / KeyType registry so callers choose which algorithms (and RSA modulus sizes) are accepted. Each crypto/<algo> package exposes KeyType(); crypto/all blank-import registers everything into DefaultKeySet, which starts empty until you Register or import all.

DID resolution gains did.WithKeySet(...): did:key and did:plc decode embedded publicKeyMultibase only through the selected set, so mismatched policies fail resolution. did:key parse no longer validates the key until Document(). Multikey unmarshaling uses crypto.PublicKeyFromMultibase (default set).

RSA did:key multibase encoding/decoding switches from PKIX DER to PKCS#1 RSAPublicKey DER, aligned with the spec; KeyType can restrict allowed RSA bit lengths.

Tests add _ "crypto/all" where full algorithm support is needed and cover KeySet restriction for did:key, did:plc, and package-level crypto behavior.

Reviewed by Cursor Bugbot for commit b6ba90a. 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.

@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 2 potential issues.

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 b6ba90a. Configure here.

)
require.Error(t, 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.

Tests omit key registration

Medium Severity

Resolution now decodes keys in Document() via DefaultKeySet, which starts empty unless algorithms are registered. These in-package tests call Document() without WithKeySet or a blank crypto/all import, so they fail where they previously passed because parsing used to decode keys eagerly.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b6ba90a. Configure here.

}

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.

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