Skip to content

feat: support X25519 ECDH - UI - #1171

Open
Manuthor wants to merge 14 commits into
x25519_ecdhfrom
x25519_ecdh_ui
Open

feat: support X25519 ECDH - UI#1171
Manuthor wants to merge 14 commits into
x25519_ecdhfrom
x25519_ecdh_ui

Conversation

@Manuthor

@Manuthor Manuthor commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Add X25519 ECDH key derivation to DeriveKeyForm UI and CLI

  • Adds an X25519 derivation branch to the DeriveKeyForm React component that collects private-key and peer-public-key identifiers and sends a derive_key_asymmetric KMIP request. X25519 is disabled when FIPS mode is assumed or reported by /server-info.
  • Adds --x25519, --private-key-id, and --peer-public-key-id flags to DeriveKeyAction in the CLI, with symmetric salt made optional at parse time (still required at runtime for PBKDF2/HKDF). Symmetric HKDF now uses caller-supplied --info bytes instead of a generated timestamp/UUID context.
  • Adds non-FIPS Playwright E2E tests and CLI integration tests for X25519 derivation, and generalizes the createEcKeyPair helper to accept an optional curve argument.
  • Updates CRL/OCSP configuration docs, KMIP support matrices, and CLI command references; adds a sensitive-attribute path to CreateSecretDataAction.
  • Risk: DeriveKeyAction.build_derivation_params replaces the auto-generated HKDF context with --info (default empty); existing callers relying on the old generated context will see different derivation outputs.

Macroscope summarized c9533bd.

Adds a Web UI form for the new asymmetric (X25519 ECDH) DeriveKey
capability introduced on the x25519_ecdh backend branch:

- New WASM export derive_key_asymmetric_ttlv_request (+ matching
  response parser), wrapping DeriveKey::new_asymmetric for browser
  consumers.
- New 'X25519 ECDH' derivation method on the Derive Key page, with
  private-key / peer-public-key selectors built on the existing
  key-picker component; output is always a fixed 256-bit SecretData
  object (server-enforced), so the method requires only Derive Key
  permission on both referenced keys, not a cryptographic usage mask.
- en/zh-CN i18n strings for the new form.
- Playwright e2e coverage for the new flow (FIPS-mode skipped, since
  X25519 is non-FIPS only), and an extended EC-key-pair test helper
  supporting an explicit curve parameter.
Adds an --x25519/--private-key-id/--peer-public-key-id CLI counterpart
to the Web UI's asymmetric X25519 ECDH derivation form, per the
cli-ui-sync convention (every UI capability needs a ckms subcommand).

- New DeriveKeyAction fields (non-fips gated): x25519, private_key_id,
  peer_public_key_id. salt becomes Option<String> (unused/optional for
  X25519, still required for PBKDF2/HKDF, validated in run()).
- New run_x25519() builds a DeriveKey::new_asymmetric request directly,
  supporting the optional --derived-key-id output UID (the existing
  client helper derive_x25519_secret doesn't expose this parameter.
- clap constraints: --x25519 requires --private-key-id and
  --peer-public-key-id (requires_all on the x25519 field itself); all
  three are mutually exclusive with --key-id/--password.
- Update existing derive-key CLI tests for the new struct shape, add
  test_derive_key_x25519 (happy path + missing-required-arg error),
  and fix 7 pre-existing test assertions that predated derived_key_id
  support: the server honors a client-supplied unique_identifier for
  derived objects (both symmetric and asymmetric paths), so asserting
  a server-generated derived-* prefix was already incorrect.

Also fixes two pre-existing docs-tooling bugs that blocked pre-commit
on any change touching clap-derived structs:
- docs:generate mise task / smart pre-commit wrapper: a prior commit
  removed .mise/scripts/audit/crypto_sensor.sh but left
  generate_docs.sh's step 4 (crypto inventory) calling it
  unconditionally. Expose the script's existing --skip-crypto flag
  through the mise task and pass it from the smart regen wrapper,
  mirroring the existing --skip-cbom handling.
- renew_ckms_markdown.sh: the  generator emits a
  trailing space for subcommands with an empty help string (e.g.
  ), which fought with the trailing-whitespace
  pre-commit hook in an infinite modify/fix loop. Strip trailing
  whitespace from the generated file, mirroring the existing usage.md
  post-processing.

Regenerated all auto-derived documentation (ckms CLI reference, server
CLI/config reference, KMIP support tables) to bring it back in sync
with the current codebase, as required by the docs-regen pre-commit
hook.
EOF
)
Honor explicit HKDF context and digest defaults, preserve sensitive attributes for inline SecretData, and add the X25519 DeriveKey vector.
Comment thread documentation/docs/kms_clients/cli/main_commands.md Outdated
Comment thread ui/src/actions/Keys/DeriveKey.tsx
Comment thread ui/src/i18n/locales/en/actions.json
Comment thread documentation/docs/configuration/server_cli.md Outdated
Comment thread AGENTS.md Outdated
The --ceremony flag on `ckms sym keys create-split-key` is a valueless
boolean switch (clap bool flag), not a flag that takes a true/false
argument. `--ceremony true` fails to parse (true is read as an
unexpected positional argument). Document the bare --ceremony flag.
GET /ocsp/ (bare path, no request) 404s: the registered route is
GET /ocsp/{encoded_request}, requiring the base64url-encoded DER OCSP
request in the path (RFC 6960 A.1).
…rity

The Derive Key form offered X25519 ECDH unconditionally, but the server
rejects derive_key_asymmetric with NotSupported in FIPS mode, directing
users toward a request that can never succeed. Query /server-info once
and disable the X25519 radio option (with a "Non-FIPS only" tag) when
the server runs in FIPS mode; also flag the limitation in the intro
copy.

Also brings French to full parity with English/Chinese for the
deriveKey namespace: the fr bundle was missing all X25519 ECDH strings
(methodCard, x25519Card, x25519Intro, private/peer key labels, and the
new nonFipsOnly key), so French users saw an untranslated fallback for
the entire X25519 section. Chinese was also missing nonFipsOnly.

Excludes ui/src/i18n/locales/fr/ from the typos pre-commit hook: the
French locale bundles contain hundreds of pre-existing words the
English-dictionary spell-checker misflags (objet, raison, contient,
...), and --write-changes was silently corrupting valid French text
into English on any commit that staged these files. This mirrors the
existing exclude-list pattern already used for other non-English/
non-checkable paths in this repo.
The PR cascade guidance told agents to use gh stack sync to update
already-pushed CLI/UI branches after an earlier PR merges, but that
tool rebases and force-pushes (--force-with-lease) downstream
branches -- directly violating the absolute force-push prohibition
elsewhere in the same document. Replace the gh stack sync reference
with an explicit merge-based update flow (git merge origin/<upstream>
+ a regular fast-forward push) that keeps branch history append-only.
Pulls in the 4 review-comment/CI fixes just pushed to the server PR
(#1170) base branch: doc fixes, CHANGELOG fix, the asymmetric DeriveKey
object_type validation tightening, and the caller-supplied
derived_key_id test fixes. Resolves the derive_key_tests.rs conflict
by keeping this branch's X25519 CLI test additions alongside the
upstream exact-match assertion fix.
Comment thread documentation/docs/configuration/server_cli.md Outdated
Comment thread documentation/docs/configuration/server_cli.md
Comment thread documentation/docs/kmip_support/support.md Outdated
Comment thread documentation/docs/configuration/server_cli.md
Comment thread documentation/docs/kms_clients/cli/main_commands.md
Comment thread documentation/docs/kmip_support/support.md Outdated
Comment thread documentation/docs/configuration/server_cli.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

There are concrete correctness/testability issues (FIPS fallback behavior and brittle placeholder-based Playwright selectors for the new X25519 flow) plus notable scope drift with unrelated CRL/OCSP config changes.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR extends the client-side DeriveKey feature set by adding an X25519 ECDH (non-FIPS) derivation mode across the Web UI, WASM bindings, and ckms CLI, along with updated Playwright/CLI tests and regenerated documentation.

Changes:

  • Add X25519 ECDH mode to the Derive Key UI and Playwright E2E coverage (with FIPS-mode gating).
  • Add CLI + WASM support for asymmetric DeriveKey requests/responses (X25519), plus ckms integration tests.
  • Update generated docs/config templates and KMIP support tables (notably including new [crl] / [ocsp] sections).
File summaries
File Description
ui/tests/e2e/README.md Document the expanded DeriveKey E2E flow to include X25519 ECDH.
ui/tests/e2e/helpers.ts Generalize EC key-pair creation helper to allow selecting X25519.
ui/tests/e2e/derive-key-flow.spec.ts Add Playwright coverage for X25519 ECDH derivation.
ui/src/utils/utils.ts Formatting-only change to docsUrl.
ui/src/i18n/locales/zh-CN/actions.json Add X25519 DeriveKey UI strings (zh-CN).
ui/src/i18n/locales/fr/actions.json Add X25519 DeriveKey UI strings (fr).
ui/src/i18n/locales/en/actions.json Add X25519 DeriveKey UI strings (en).
ui/src/actions/Keys/DeriveKey.tsx Add X25519 mode to DeriveKey UI + FIPS gating via /server-info.
README.md Update KMIP support matrices in the root README.
pkg/kms.toml Add [crl] / [ocsp] configuration blocks (scope expansion beyond X25519).
documentation/docs/kms_clients/cli/main_commands.md Regenerated CLI docs reflecting new ckms flags/subcommands.
documentation/docs/kmip_support/support.md Update KMIP support tables in the docs site.
documentation/docs/configuration/server_configuration_file.md Document new server config sections and adjust Crypto Officer wording.
documentation/docs/configuration/server_cli.md Document new CLI flags (CRL/OCSP) and adjust Crypto Officer wording.
crate/server/kms_template.toml Add [crl] / [ocsp] sections to the server template.
crate/clients/wasm/src/wasm.rs Add WASM export/parser for asymmetric DeriveKey (X25519).
crate/clients/clap/src/actions/secret_data/create_secret.rs Respect --sensitive when creating SecretData from inline value.
crate/clients/clap/src/actions/derive_key/mod.rs Add --x25519 asymmetric DeriveKey path + --info for HKDF context.
crate/clients/ckms/src/tests/secret_data/mod.rs Register new secret_data lifecycle tests.
crate/clients/ckms/src/tests/secret_data/lifecycle.rs Add test ensuring sensitive inline SecretData blocks export.
crate/clients/ckms/src/tests/derive_key/derive_key_tests.rs Add/adjust ckms derive-key tests including X25519 coverage.
CHANGELOG/x25519_ecdh_ui.md Add branch changelog entry for the feature and tests.
AGENTS.md Add/clarify workflow rules (PR cascade + force-push prohibition).
.pre-commit-config.yaml Expand typos exclude list to skip French locale directory.
.mise/tasks/docs/generate Add --skip-crypto passthrough flag.
.mise/scripts/pre-commit/smart-docs-regen.sh Use --skip-crypto during smart docs regen.
.mise/scripts/docs/renew_ckms_markdown.sh Strip trailing whitespace after docs regeneration.
.github/copilot-instructions.md Add PR cascade + force-push prohibition guidance.
Review details

Suppressed comments (1)

ui/src/actions/Keys/DeriveKey.tsx:232

  • The X25519 custom output ID field is currently only identifiable via its placeholder text. Add a data-testid so E2E tests (and future automation) don’t depend on English copy.
                            <Form.Item name="derivedKeyId" label={t("deriveKey.derivedKeyId")} help={t("deriveKey.derivedKeyIdHelp")}>
                                <Input placeholder={t("deriveKey.derivedKeyIdPlaceholder")} />
                            </Form.Item>
  • Files reviewed: 28/28 changed files
  • Comments generated: 6
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ui/src/actions/Keys/DeriveKey.tsx Outdated
Comment thread .pre-commit-config.yaml
Comment thread pkg/kms.toml
Comment thread ui/src/actions/Keys/DeriveKey.tsx
Comment thread ui/tests/e2e/derive-key-flow.spec.ts
Comment thread ui/tests/e2e/derive-key-flow.spec.ts Outdated
…racies

- OCSP: correct endpoint path (GET /ocsp/{encoded_request} + POST /ocsp/),
  clarify delegated signing key is not routed through crypto_oracles (HSM
  non-extractable keys fail), and clarify --ocsp-include-cert-chain only
  embeds the signer cert, not the full chain.
- CRL: clarify crl_default_validity_days is in whole days (min 24h) and can
  conflict with the default 24h refresh-overlap; clarify the refresh
  scheduler requires kms_public_url to be set to run at all.
- ckms: clarify --ceremony / --total-parts fallback behavior for callers who
  are not eligible Crypto Officer candidates.
- KMIP support tables (support.md + README.md): Create Split Key is KMIP 1.3+
  (not 1.2); ECDH Private/Public Key is decodable in KMIP 1.4 (aliased to
  TransparentECPrivateKey).

All doc fixes are sourced from the corresponding clap doc comments and
regenerated via 'mise run docs:generate server-docs' to keep server_cli.md,
server_configuration_file.md, kms_template.toml and pkg/kms.toml in sync.
…for X25519 DeriveKey

- DeriveKey.tsx: default isFips=true (and re-set true in the /server-info
  catch path) so a failed FIPS-mode probe fails closed (X25519 option stays
  hidden/disabled) instead of silently allowing a request the server will
  reject in FIPS mode.
- Add stable data-testid props (x25519-private-key-id, x25519-peer-public-key-id,
  x25519-derived-key-id) to the X25519 form fields so E2E tests don't depend on
  translated placeholder text.
- derive-key-flow.spec.ts: switch the X25519 E2E scenarios to page.getByTestId(...)
  selectors per the repo's Playwright convention (data-testid over placeholder text).
Comment thread documentation/docs/configuration/server_configuration_file.md Outdated
Comment thread documentation/docs/configuration/server_configuration_file.md
Comment thread crate/server/kms_template.toml
- Add ocsp_ca_uid (required when ocsp_enabled=true) and ocsp_responder_cert_uid
  as commented-out example fields in kms_template.toml, since they were
  entirely absent from the generated example config, silently omitting a
  field that is mandatory to actually enable the OCSP responder.
- crl_default_validity_days: clarify that the documented 1-365 range is
  enforced by clap only for CLI/env input, and is not currently re-validated
  when the value comes from a TOML config file.
- Regenerated server_cli.md, server_configuration_file.md, pkg/kms.toml from
  the updated source doc comments.
Comment thread documentation/docs/configuration/server_configuration_file.md Outdated
…y_days doc

CrlConfig has no clap env bindings, so the previous fix's wording implying
an environment-variable path is also validated was itself inaccurate — only
the CLI flag is range-validated.
Comment thread documentation/docs/configuration/server_cli.md
…a CLI

The clap field is a bare boolean switch (ArgAction::SetTrue), so
--ocsp-include-cert-chain can only ever set the value to true (already the
default); there is no CLI syntax to pass false. Clarified that disabling it
requires the TOML config file instead.
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.

2 participants