Skip to content

Fix engineGetCertificateAlias returning the alias of an unrelated certificate - #2385

Closed
rimuln wants to merge 1 commit into
bcgit:mainfrom
rimuln:fix/pkcs12-get-certificate-alias
Closed

Fix engineGetCertificateAlias returning the alias of an unrelated certificate#2385
rimuln wants to merge 1 commit into
bcgit:mainfrom
rimuln:fix/pkcs12-get-certificate-alias

Conversation

@rimuln

@rimuln rimuln commented Aug 3, 2026

Copy link
Copy Markdown

Fixes #2384.

PKCS12KeyStoreSpi.engineGetCertificateAlias walked certs.elements() and certs.keys() in
lockstep, taking the certificate from one enumeration and the alias from the other. That relies on
both enumerations visiting the table in the same order, which stopped being true in 1.80: a5be993
changed IgnoresCaseHashtable.keys() to enumerate new Hashtable(orig) while elements() still
enumerates orig. new Hashtable(Map) sizes its bucket array from the entry count, whereas orig
reached its capacity by incremental rehashing, so once a store holds enough entries the two layouts
differ and the method returns the alias of an unrelated certificate — silently, with no exception.

Since the copy in keys() was introduced deliberately, this fixes the caller instead of reverting
it: the value is now looked up by key, so the result no longer depends on two enumerations agreeing.
The same change is applied to the keyCerts loop below it — keyCerts is a plain Hashtable whose
keys() and elements() do agree, so it was not broken, but the pairing was the same latent
fragility and removing it costs nothing.

testGetCertificateAlias in PKCS12StoreTest covers it: 12 certificate entries, then every
certificate is looked up and must return its own alias, plus a negative case for a certificate that
is not in the store. Twelve is chosen so the backing table has grown past its initial capacity — with
only a handful of entries the original and the copy can share a layout and the defect does not
reproduce, which is probably why it went unnoticed. The test fails before this change and passes
after.

Not addressed here: the prov/src/main/jdk1.3 and prov/src/main/jdk1.4 copies of this class still
have return orig.keys(); and so behave correctly today, but their engineGetCertificateAlias
carries the same order-dependent pairing. Happy to extend the PR to those trees if you would prefer
them hardened too.

Prepared with AI assistance (noted in the commit trailer), offered under the Bouncy Castle License
per CONTRIBUTING.md.

…tificate

engineGetCertificateAlias took the certificate from certs.elements() and the
alias from certs.keys(), advancing both in lockstep. That relies on the two
enumerations visiting the table in the same order, which stopped holding when
IgnoresCaseHashtable.keys() began enumerating a copy of the table while
elements() kept enumerating the original: new Hashtable(Map) sizes its bucket
array from the entry count, whereas the original reached its capacity by
incremental rehashing, so for a store with enough entries the layouts differ and
the method returns the wrong alias with no error.

Look the value up by key instead, which does not depend on the two enumerations
agreeing. Applied to the keyCerts loop as well - keyCerts is a plain Hashtable
whose keys() and elements() do agree, so it was not affected, but the pairing was
the same latent fragility.

testGetCertificateAlias covers it with 12 certificate entries plus a negative
case; twelve is needed because with only a few entries the table and its copy can
share a layout and the defect does not reproduce.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dghgit

dghgit commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Thanks, merged with minor revision, now up on https://www.bouncycastle.org/betas

@dghgit dghgit closed this Aug 4, 2026
hubot pushed a commit that referenced this pull request Aug 4, 2026
…consistency test and cite rimuln's PR in the CONTRIBUTORS entry, relates to github #2384 and PR #2385.
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.

PKCS12KeyStoreSpi.engineGetCertificateAlias returns the alias of an unrelated certificate (since 1.80)

2 participants