Repository navigation
Compare asymmetric keys by value through the base interface - #204
Merged
Merged
Conversation
TAsymmetricKeyParameter.Equals only compared the public/private flag, so any two public keys (or any two private keys) reachable only as IAsymmetricKeyParameter compared equal regardless of their key material. Value equality lived on the family sub-interfaces as typed overloads, unreachable without knowing the concrete family. Route the base Equals through a protected virtual SameKey hook that every concrete key type overrides: classical families dispatch to their typed Equals, and the PQ families compare parameter set plus a constant-time compare of the encoded key. The base default is fail-closed identity, so an un-overridden type is equal only to itself. DH and DSA tolerate nil domain parameters so Equals never raises.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
TAsymmetricKeyParameter.Equals(the baseIAsymmetricKeyParameter.Equals) compared only thepublic/private flag:
Result := FPrivateKey = AOther.PrivateKey. So any two public keys — or any twoprivate keys — held as the base
IAsymmetricKeyParametercompared equal regardless of their keymaterial. Callers that only have the base interface (chain/credential code comparing a leaf's key
against a candidate) had no correct value comparison available; the real value equality lived on the
family sub-interfaces (
IRsaKeyParameters.Equals,IECPublicKeyParameters.Equals, …) as typedoverloads, unreachable without first knowing the concrete family.
Change
The base
Equalsnow routes through aprotected virtual SameKeyhook that every concrete key typeoverrides:
existing typed
Equalsafter a familySupportscheck — so a key of another family is simply notequal.
SameTexton the parameters'name — nil-safe, and distinguishes same-length sets such as SLH-DSA sets sharing
n, or ML-DSApure vs pre-hash) plus a constant-time compare of the encoded key.
EqualsreturnsFalseforniland never raises: DH and DSA additionally toleratenildomainparameters (consistent with their existing
GetHashCodenil-guard).SameKeyis a protected hook rather than anoverrideofEqualsbecause a virtual override of amethod that also has typed
reintroduce; overloadsiblings does not compile cleanly across bothsupported compilers; the hook keeps a single interface-visible
Equalswhile letting each familysupply the comparison.
Tests
Added
TestBaseInterfaceEqualsComparesValue(RSA, via the baseIAsymmetricKeyParameter): equal keymaterial compares equal, differing material does not (a flag-only check would wrongly say equal), a
key equals itself, and a key does not equal
nil.Full suite green on FPC x86_64, FPC i386, and Delphi Win32 (1577 tests, 0 failures on each).