Skip to content

camel-crypto: resolve secureRandomName without needing a keystore - #29707

Merged
davsclaus merged 1 commit into
apache:mainfrom
Dhairya-007:fix/crypto-secure-random-name
Nov 12, 2026
Merged

davsclaus merged 1 commit into
apache:mainfrom
Dhairya-007:fix/crypto-secure-random-name

Conversation

@Dhairya-007

Copy link
Copy Markdown
Contributor

Problem

DigitalSignatureConfiguration has five "reference name" options that look an object up in the registry and apply it if the lookup found one. Four of them guard on the value they just looked up:

public void setKeystoreName(String keystoreName) {
    if (context != null && keystoreName != null) {
        KeyStore keystore = context.getRegistry().lookupByNameAndType(keystoreName, KeyStore.class);
        if (keystore != null) {
            setKeystore(keystore);
        }
    }
    ...

setPublicKeyName, setPrivateKeyName and setCertificateName are the same shape, each guarding on its own local (pk, pk, certificate).

setSecureRandomName copied that guard, but its local is called random — so keystore in the condition is the field, which has nothing to do with the lookup:

public void setSecureRandomName(String randomName) {
    if (context != null && randomName != null) {
        SecureRandom random = context.getRegistry().lookupByNameAndType(randomName, SecureRandom.class);
        if (keystore != null) {          // the field, not the value just looked up
            setSecureRandom(random);
        }
    }
    ...

Two consequences:

  • secureRandomName is silently ignored unless a KeyStore object is already set on the configuration. Signing or verifying with a plain privateKey/publicKey, which is what the component's own tests do, never sets one, so the SecureRandom the user named is resolved and then dropped, and the Signature is initialised without it.
  • When a keystore is set and the name resolves to nothing, the condition is true anyway and setSecureRandom(null) wipes a SecureRandom that was configured directly through secureRandom.

setCamelContext re-runs all five setters once the context is known, so the bug does not depend on the order the options are set in — it is not reachable at all without a keystore.

Fix

Guard on random, like the four siblings.

Tests

New DigitalSignatureConfigurationTest:

  • secureRandomNameShouldResolveWithoutAKeystore — the named SecureRandom is used when no keystore is configured. Fails on main.
  • secureRandomNameShouldResolveTheSameWayAsTheOtherReferenceNames — the name set before the context is known is resolved by setCamelContext, as the other reference names are. Fails on main.
  • anUnknownSecureRandomNameShouldNotClearTheConfiguredOne — a name that resolves to nothing leaves a directly configured SecureRandom alone. This is the second half of the bug; it passes either way without a keystore, and pins the behaviour.

The five reference-name setters of DigitalSignatureConfiguration look their
object up in the registry and apply it when the lookup found something. Four
of them guard on the value they just looked up:

    KeyStore keystore = context.getRegistry().lookupByNameAndType(keystoreName, KeyStore.class);
    if (keystore != null) {
        setKeystore(keystore);
    }

setSecureRandomName copied that guard but named its local `random`, so
`keystore` there is the *field*:

    SecureRandom random = context.getRegistry().lookupByNameAndType(randomName, SecureRandom.class);
    if (keystore != null) {        // the field, unrelated to the lookup
        setSecureRandom(random);
    }

So secureRandomName only takes effect when a KeyStore happens to be set on
the configuration already - which signing or verifying with a plain key never
does - and the resolved SecureRandom is dropped on the floor. When a keystore
is set and the name resolves to nothing, the opposite happens and
setSecureRandom(null) wipes a SecureRandom that was configured directly.

The guard now tests `random`, like its four siblings.

@gnodet-bot gnodet-bot 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.

LGTM. The one-character fix (keystore → random in the guard) is correct — setSecureRandomName was the only one of the five reference-name setters that guarded on the wrong variable, and the three tests cover exactly the three failure modes described in the PR description.

Pre-fix validation: static trace confirms all three tests would have been failing on main before the fix:

  • secureRandomNameShouldResolveWithoutAKeystore — keystore == null in a keystore-less config, so setSecureRandom(random) was never called → assertSame fails ✅
  • secureRandomNameShouldResolveTheSameWayAsTheOtherReferenceNames — same path in setCamelContext re-runs → assertSame fails ✅
  • anUnknownSecureRandomNameShouldNotClearTheConfiguredOne — random == null after a failed lookup but keystore != null guard would have passed and called setSecureRandom(null), wiping the directly configured instance → assertSame fails ✅

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@davsclaus davsclaus 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.

TL;DR: LGTM, a precise one-word fix with good tests.

setSecureRandomName was the only one of the five reference-name setters that guarded on the field keystore rather than the value it had just looked up. Guarding on random brings it in line with setKeystoreName/setPublicKeyName/setPrivateKeyName/setCertificateName, and since setCamelContext re-runs all five, the named SecureRandom now reaches SigningProcessor with or without a keystore.

One optional improvement: anUnknownSecureRandomNameShouldNotClearTheConfiguredOne passes on main as well, since no keystore is configured. If you set an empty keystore first (KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(null, null); configuration.setKeystore(ks);), it would fail on main (the old guard calls setSecureRandom(null)) and pin the second half of the bug.

Claude Code on behalf of davsclaus. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-crypto

🔬 Scalpel shadow comparison — Scalpel: 10 of 723 tested, 27 compile-only — current: 10 all tested

Maveniverse Scalpel detected 10 affected modules (current approach: 10).

Skip-tests mode would test 10 modules (1 direct + 9 downstream), skip tests for 27 (generated code, meta-modules)

Modules Scalpel would test (10)
  • camel-crypto ← components/camel-crypto/src/main/java/org/apache/camel/component/crypto/DigitalSignatureConfiguration.java, components/camel-crypto/src/test/java/org/apache/camel/component/crypto/DigitalSignatureConfigurationTest.java
  • camel-jbang-mcp ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-mcp ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-tui ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-validate ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-jbang-run ← downstream of org.apache.camel:camel-catalog
  • camel-launcher-container ← downstream of org.apache.camel:camel-launcher
  • camel-pqc ← downstream of org.apache.camel:camel-crypto
  • camel-yaml-dsl-validator ← downstream of org.apache.camel:camel-catalog
  • camel-yaml-dsl-validator-maven-plugin ← downstream of org.apache.camel:camel-yaml-dsl-validator
Modules with tests skipped (27)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (37 modules, 6m 35s total)

Total reactor time: 6m 35s

Module Duration Status
Camel :: JBang :: Plugin :: TUI 57.8s SUCCESS
Camel :: Launcher 56.5s SUCCESS
Camel :: PQC 42.4s SUCCESS
Camel :: JBang :: MCP 36.1s SUCCESS
Camel :: YAML DSL 22.0s SUCCESS
Camel :: JBang :: Plugin :: Validate 21.9s SUCCESS
Camel :: YAML DSL :: Validator 21.4s SUCCESS
Camel :: Component DSL 18.4s SUCCESS
Camel :: Catalog :: Camel Catalog 15.7s SUCCESS
Camel :: JBang :: Run 14.6s SUCCESS
Camel :: Crypto 11.9s SUCCESS
Camel :: Docs 10.4s SUCCESS
Camel :: Kamelet Main 8.9s SUCCESS
Camel :: JBang :: Plugin :: Testing 8.7s SUCCESS
Camel :: JBang :: Plugin :: Kubernetes 8.3s SUCCESS
Camel :: Catalog :: Camel Report Maven Plugin 6.5s SUCCESS
Camel :: YAML DSL :: Deserializers 5.2s SUCCESS
Camel :: Catalog :: Camel Route Parser 4.8s SUCCESS
Camel :: JBang :: Plugin :: Generate 4.0s SUCCESS
Camel :: All Components Sync point 3.2s SUCCESS
Camel :: Assembly 2.1s SUCCESS
Camel :: Catalog :: Maven 2.0s SUCCESS
Camel :: YAML DSL :: Maven Plugins 2.0s SUCCESS
Camel :: YAML DSL :: Validator Maven Plugin 1.9s SUCCESS
Camel :: Catalog :: Suggest (deprecated) 1.5s SUCCESS
Camel :: Catalog :: Dummy Component 1.0s SUCCESS
Camel :: JBang :: Integration tests 0.9s SUCCESS
Camel :: Catalog :: Console 0.9s SUCCESS
Camel :: Coverage 0.8s SUCCESS
Camel :: JBang :: Plugin :: MCP 0.7s SUCCESS
Camel :: Endpoint DSL :: Support 0.7s SUCCESS
Camel :: JBang :: Plugin :: Edit 0.6s SUCCESS
Camel :: JBang :: Main 0.6s SUCCESS
Camel :: Launcher :: Container 0.5s SUCCESS
Camel :: Endpoint DSL n/a
Camel :: Integration Tests n/a
Camel :: JBang :: Core n/a

Top 20 slowest modules:

  • Camel :: JBang :: Plugin :: TUI (57.8s)
  • Camel :: Launcher (56.5s)
  • Camel :: PQC (42.4s)
  • Camel :: JBang :: MCP (36.1s)
  • Camel :: YAML DSL (22.0s)
  • Camel :: JBang :: Plugin :: Validate (21.9s)
  • Camel :: YAML DSL :: Validator (21.4s)
  • Camel :: Component DSL (18.4s)
  • Camel :: Catalog :: Camel Catalog (15.7s)
  • Camel :: JBang :: Run (14.6s)
  • Camel :: Crypto (11.9s)
  • Camel :: Docs (10.4s)
  • Camel :: Kamelet Main (8.9s)
  • Camel :: JBang :: Plugin :: Testing (8.7s)
  • Camel :: JBang :: Plugin :: Kubernetes (8.3s)
  • Camel :: Catalog :: Camel Report Maven Plugin (6.5s)
  • Camel :: YAML DSL :: Deserializers (5.2s)
  • Camel :: Catalog :: Camel Route Parser (4.8s)
  • Camel :: JBang :: Plugin :: Generate (4.0s)
  • Camel :: All Components Sync point (3.2s)

⚙️ View full build and test results

@oscerd oscerd 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.

Confirmed the bug and the fix, and checked the sibling setters.

setSecureRandomName looked up the SecureRandom by name but then applied it under if (keystore != null) rather than if (random != null). Two consequences: a secureRandomName was silently ignored whenever no keystore was configured (the common case for a detached-signature route that only needs a custom RNG), and when a keystore was present but the name resolved to nothing it would push a null SecureRandom over whatever was already set. Guarding on random is the right fix.

I checked the other four reference-name setters to be sure this was the only one off: setKeystoreName guards on keystore, setPublicKeyName and setPrivateKeyName on their pk, and setCertificateName on certificate, each on the value it just looked up. setSecureRandomName was the only one keyed on a different variable, so this brings it in line with the rest.

The three tests pin the behavior well: resolution without any keystore, resolution deferred until setCamelContext re-applies the names (so the order the configurer sets options in does not matter), and an unknown name leaving an already-configured SecureRandom untouched rather than clearing it. Good.

Claude Code on behalf of oscerd

@davsclaus davsclaus added this to the 4.24.0 milestone Nov 12, 2026
@davsclaus davsclaus added the bug Something isn't working label Nov 12, 2026
@davsclaus
davsclaus merged commit a4de368 into apache:main Nov 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants