-
Notifications
You must be signed in to change notification settings - Fork 3
feat(sdk): support ML-KEM rewrap session keys #388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dmihalcik-virtru
wants to merge
1
commit into
main
Choose a base branch
from
DSPX-4221-pq-sessions
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
43 changes: 43 additions & 0 deletions
43
sdk-pqc-bc/src/test/java/io/opentdf/platform/sdk/pqc/bc/HybridCryptoGenerateKeyPairTest.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package io.opentdf.platform.sdk.pqc.bc; | ||
|
|
||
| import io.opentdf.platform.sdk.KeyType; | ||
| import io.opentdf.platform.sdk.spi.KemProvider; | ||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.EnumSource; | ||
|
|
||
| import java.nio.charset.StandardCharsets; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertArrayEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
|
||
| /** | ||
| * Unit tests for {@link HybridCrypto#generateKeyPair}, the dispatcher backing | ||
| * {@link BouncyCastleKemProvider#generateKeyPair} and (in the core {@code sdk} | ||
| * module) {@code KASClient}'s KEM branch for the rewrap client "session key". | ||
| * | ||
| * <p>Each variant is exercised end-to-end through the same PEM-based | ||
| * {@link KemProvider} contract KASClient uses: generate a fresh keypair, wrap | ||
| * a DEK against its public PEM, unwrap against its private PEM, assert equal. | ||
| */ | ||
| class HybridCryptoGenerateKeyPairTest { | ||
|
|
||
| private static final byte[] DEK = "0123456789abcdef0123456789abcdef".getBytes(StandardCharsets.UTF_8); | ||
|
|
||
| @ParameterizedTest | ||
| @EnumSource(value = KeyType.class, names = { | ||
| "HybridXWingKey", | ||
| "HybridSecp256r1MLKEM768Key", | ||
| "HybridSecp384r1MLKEM1024Key", | ||
| "MLKEM768Key", | ||
| "MLKEM1024Key"}) | ||
| void generatedKeyPairRoundTrips(KeyType keyType) { | ||
| KemProvider.KeyPairPem kp = HybridCrypto.generateKeyPair(keyType); | ||
|
|
||
| assertTrue(kp.publicKeyPEM.startsWith("-----BEGIN PUBLIC KEY-----"), "public PEM header"); | ||
| assertTrue(kp.privateKeyPEM.startsWith("-----BEGIN PRIVATE KEY-----"), "private PEM header"); | ||
|
|
||
| byte[] wrapped = HybridCrypto.wrapDEK(keyType, kp.publicKeyPEM, DEK); | ||
| byte[] unwrapped = HybridCrypto.unwrapDEK(keyType, kp.privateKeyPEM, wrapped); | ||
| assertArrayEquals(DEK, unwrapped, "DEK round-trip via generated keypair"); | ||
| } | ||
| } |
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
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Guard the lazy RSA key-pair initialization against concurrent
unwrap()calls.The EC and ML-KEM branches now correctly return per-call local key material, which fixes the previously flagged race on the shared
clientPublicKeyfield. The RSA branch still has a check-then-act race:if (decryptor == null)at Line 147 reads and later writes the shared, non-volatilefieldsdecryptorandclientPublicKeywithout synchronization.If two threads call
unwrap()with an RSA session key type beforedecryptoris first set, both can generate distinct RSA key pairs and race to overwrite each other'sdecryptor/clientPublicKey. One call can then send a public key from one generation while decrypting the response with a different generation's private key, causing decryption failures. This class already synchronizesclose()(Line 110) andgetStub()(Line 233), so concurrent use of the sameKASClientinstance is an expected usage pattern, not a theoretical edge case.Synchronize the lazy-init block with double-checked locking, and mark
decryptorandclientPublicKeyvolatileso the initializing thread's write is visible to other threads.🔒 Proposed fix: synchronize the lazy RSA key-pair initialization
🤖 Prompt for AI Agents