Skip to content

feat(core): Deprecate ECKeyPair in favor of asym_*#3293

Draft
dmihalcik-virtru wants to merge 9 commits intomainfrom
DSPX-1089-deprecate-eckp
Draft

feat(core): Deprecate ECKeyPair in favor of asym_*#3293
dmihalcik-virtru wants to merge 9 commits intomainfrom
DSPX-1089-deprecate-eckp

Conversation

@dmihalcik-virtru
Copy link
Copy Markdown
Member

@dmihalcik-virtru dmihalcik-virtru commented Apr 10, 2026

Proposed Changes

  • Deprecates ECKeyPair, which is largely redundant with AsymDecrypt and AsymEncrypt
  • This focuses interfaces on use, not on implemenation details
  • Further, you often will only have a public part, and only use that, so the metaphor is just confusing.
  • Removes the direct computation of shared secrets, which is no longer directly used, and unsupported by FIPS Level 3 hardware.

Checklist

  • I have added or updated unit tests
  • I have added or updated integration tests (if appropriate)
  • I have added or updated documentation

Testing Instructions

Summary by CodeRabbit

  • New Features

    • New private-key decryptor factory and richer key APIs (private PEM export, public-key derivation, key-type reporting); EC encryptors now expose ephemeral public-key PEM.
  • Deprecations

    • Legacy EC/keypair helpers marked deprecated; new PrivateKeyDecryptor-based APIs preferred.
  • Bug Fixes

    • Improved ephemeral key generation/validation and clearer error messages for unsupported key types.
  • Tests

    • Added/updated tests covering asymmetric key creation, ECIES-style wrap/unwrap, and public/ephemeral PEM flows.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 10, 2026

Warning

Rate limit exceeded

@dmihalcik-virtru has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 51 minutes and 3 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 51 minutes and 3 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4d923bfe-73a2-4a8d-bfb3-3a1995917e93

📥 Commits

Reviewing files that changed from the base of the PR and between c7b0b7f and c8e7433.

📒 Files selected for processing (1)
  • lib/ocrypto/asym_decryption.go
📝 Walkthrough

Walkthrough

Refactors asymmetric key APIs: introduces PrivateKeyDecryptor/PublicKeyEncryptor methods and factories, centralizes PEM helpers, changes EC ephemeral key handling (adds EphemeralPublicKeyInPemFormat), and updates SDK and service call sites to use new decryptor/encryptor interfaces. Also adds tests and minor gitignore newline fix.

Changes

Cohort / File(s) Summary
Gitignore
/.gitignore
Added a trailing newline to the .claude/ ignore rule (no other ignore changes).
OCrypto: asym decryption
lib/ocrypto/asym_decryption.go
Added PrivateKeyInPemFormat(), Public(), KeyType() to PrivateKeyDecryptor; added NewPrivateKeyDecryptor and NewECPrivateKey; implemented EC/RSA decryptor methods; refactored ephemeral-key parsing and curve conversion to return errors.
OCrypto: asym decryption tests
lib/ocrypto/asym_decryption_test.go
New tests exercising decryptor/encryptor construction, PEM round-trips, KeyType checks, nil-value guards, and ECIES-style round-trips across supported curves.
OCrypto: asym encryption
lib/ocrypto/asym_encryption.go
Tighter error handling in newECIES; PublicKeyInPemFormat() now uses recipient public key; added EphemeralPublicKeyInPemFormat(); safer ephemeral key handling in Metadata/EphemeralKey.
OCrypto: EC utilities & keypair
lib/ocrypto/ec_key_pair.go
Introduced curveFromECCMode, shared PEM helpers (privateKeyInPemFormat, publicKeyInPemFormat), added Decrypt, Public, KeyType, DeriveSharedKey on ECKeyPair, and deprecated older KeyPair APIs.
OCrypto: EC tests updates
lib/ocrypto/ec_key_pair_test.go, lib/ocrypto/ec_decrypt_compressed_test.go
Tests updated to use NewECPrivateKey + Public() and to exercise EC encrypt/decrypt flows via new APIs; assertions simplified and ECDH manual derivation removed.
OCrypto: RSA keypair
lib/ocrypto/rsa_key_pair.go
PEM serialization now delegates to shared helpers; added Decrypt, Public, KeyType; GetKeyType() returns dynamic key type.
SDK: codegen
sdk/codegen/runner/generate.go
Switch to fmt.Fprintf when assembling generated interface text (internal string building change).
SDK: TDF core & config
sdk/tdf.go, sdk/tdf_config.go
Reader/config session key type changed from ocrypto.KeyPairocrypto.PrivateKeyDecryptor; WithSessionKeyType uses NewPrivateKeyDecryptor; EC wrapping now uses Encrypt() + ephemeral PEM export instead of manual ECDH/HKDF/AES-GCM.
SDK: KAS client & tests
sdk/kas_client.go, sdk/kas_client_test.go, sdk/tdf_test.go
KAS client uses ocrypto.PrivateKeyDecryptor; EC response processing now calls DecryptWithEphemeralKey; tests updated to use ocrypto ECIES APIs and ephemeral PEM exports.
SDK: experimental key access
sdk/experimental/tdf/key_access.go, sdk/experimental/tdf/key_access_test.go
wrapKeyWithPublicKey now parses public PEM once and dispatches to EC/RSA wrappers; EC wrapper uses Encrypt() and EphemeralPublicKeyInPemFormat(); tests updated accordingly.
Service: basic manager & provider
service/internal/security/basic_manager.go, service/internal/security/in_process_provider.go, service/internal/security/basic_manager_test.go
EC path now type-asserts to ocrypto.ECDecryptor; DeriveKey implementations removed/replaced with deprecated stubs returning "unsupported operation"; tests adjusted to use separate decryptor/encryptor helpers and DeriveKey tests removed.
Service: KAS rewrap
service/kas/access/rewrap.go
When constructing session public key for EC rewrap, use encryptor's ephemeral PEM (EphemeralPublicKeyInPemFormat()) instead of recipient public PEM.
Service: trust docs
service/trust/key_manager.go
Doc comments updated: Decrypt now documented as returning ProtectedKey for Key Access Object unwrapping; DeriveKey marked deprecated.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 I hopped through keys with nimble paws,

Split pairs apart with careful laws,
PEMs now sing in tidy rows,
Ephemeral blooms where mystery grows.
Encryptors, decryptors — a fresh new chore! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main objective: deprecating ECKeyPair in favor of asymmetric encryption/decryption APIs, which aligns with the core changes throughout the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DSPX-1089-deprecate-eckp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added comp:sdk A software development kit, including library, for client applications and inter-service communicati comp:kas Key Access Server comp:lib:ocrypto size/m labels Apr 10, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the cryptographic key management system by deprecating the ECKeyPair struct and introducing a more abstract PrivateKeyDecryptor interface. This change streamlines how private keys are handled across different algorithms (RSA and EC), focusing on a consistent API for key operations rather than specific implementation types. It enhances flexibility, especially for scenarios involving public-only key usage, and centralizes key generation and PEM encoding logic, leading to a cleaner and more maintainable codebase.

Highlights

  • Deprecation of ECKeyPair: The ECKeyPair struct has been deprecated in favor of new, more flexible interfaces, aligning with a focus on usage rather than implementation details.
  • Introduction of PrivateKeyDecryptor Interface: A new PrivateKeyDecryptor interface has been introduced, providing a unified way to handle private key operations such as PEM formatting, public key derivation, key type identification, and shared key derivation for both RSA and EC keys.
  • Refactored Key Management: Key generation, PEM encoding, and shared key derivation logic have been refactored to utilize the new PrivateKeyDecryptor and PublicKeyEncryptor interfaces, centralizing common cryptographic operations and improving consistency.
  • SDK and Service Integration: The SDK and various service components have been updated to consume the new PrivateKeyDecryptor interface, ensuring that all key-related operations leverage the standardized API.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.


Old key pairs now must fade, New interfaces take their place, Decryption's path is made.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the PrivateKeyDecryptor interface to unify RSA and EC private key operations, such as decryption and shared secret derivation, across the ocrypto package and SDK. It refactors RsaKeyPair, ECKeyPair, and KASClient to implement this interface while deprecating legacy functions. Feedback suggests that several nil checks in the KeyType methods are redundant and should be removed to simplify the code and avoid hiding initialization issues.

Comment on lines +161 to +163
if asymDecryption.PrivateKey == nil {
return KeyType("rsa:[unknown]")
}
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.

medium

The check for asymDecryption.PrivateKey == nil is redundant here because PrivateKey is a field of the struct and the method is called on an instance. If the instance is initialized, this field should be checked at the point of creation or usage, not inside every getter method. This adds unnecessary complexity.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yeah, that would make sense.. unfortunately FromRSA and the corresponding SDK WithSession...RSA options don't return error so it would be hard to wire that in at the moment

Comment on lines +230 to +232
if e.sk == nil {
return KeyType("ec:[unknown]")
}
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.

medium

Similar to the RSA implementation, checking for e.sk == nil inside the KeyType() method is defensive programming that might hide initialization issues. It is better to ensure the struct is properly initialized upon creation.

Comment on lines +250 to +252
if keyPair.PrivateKey == nil {
return KeyType("ec:[unknown]")
}
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.

medium

Checking for keyPair.PrivateKey == nil in KeyType() is redundant if the struct is properly initialized. Consider removing this check to simplify the method.

Comment on lines +64 to +66
if keyPair.privateKey == nil {
return KeyType("rsa:[unknown]")
}
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.

medium

The check for keyPair.privateKey == nil is redundant. If the RsaKeyPair struct is properly initialized, this field should be valid. Removing this check simplifies the code.

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 180.391028ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 99.19104ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 423.614297ms
Throughput 236.06 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 41.275696322s
Average Latency 410.605051ms
Throughput 121.14 requests/second

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 195.997865ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 101.572525ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 399.973892ms
Throughput 250.02 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 39.794970893s
Average Latency 395.202366ms
Throughput 125.64 requests/second

dmihalcik-virtru and others added 2 commits April 14, 2026 12:11
- Remove DeriveSharedKey from PrivateKeyDecryptor interface, eliminating
  false mutual-exclusion between RSA and EC implementations
- Replace SDK encrypt-side DeriveSharedKey with FromPublicPEMWithSalt+Encrypt
  in generateWrapKeyWithEC (tdf.go)
- Replace SDK decrypt-side DeriveSharedKey with DecryptWithEphemeralKey
  in handleECKeyResponse/processECResponse (kas_client.go)
- Service-side and experimental XOR callers type-assert to ECDecryptor
  and call DeriveSharedKey on the concrete type directly
- Fix silent failure chain in newECIES, EphemeralKey, and Metadata
- Fix convCurve to return error instead of nil (prevents nil-panic)
- Extract parseEphemeralPublicKey helper to fix nestif lint violation
- Fix ECKeyPair.Decrypt/Public/DeriveSharedKey to use NewECDecryptor
  so TDF salt is propagated correctly through the shim
- Add asym_decryption_test.go with coverage for new interface and methods
- Update ec_key_pair_test.go and ec_decrypt_compressed_test.go to use
  non-deprecated APIs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Dave Mihalcik <dmihalcik@virtru.com>
@dmihalcik-virtru dmihalcik-virtru force-pushed the DSPX-1089-deprecate-eckp branch from 66d1f7d to 08055b2 Compare April 14, 2026 16:12
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 196.407073ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 98.234692ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 404.879425ms
Throughput 246.99 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 40.142066379s
Average Latency 399.563177ms
Throughput 124.56 requests/second

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 202.612075ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 105.178396ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 404.347861ms
Throughput 247.31 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 41.825852469s
Average Latency 416.426574ms
Throughput 119.54 requests/second

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 149.451429ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 77.16167ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 390.987148ms
Throughput 255.76 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 38.804898061s
Average Latency 386.655783ms
Throughput 128.85 requests/second

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 196.97842ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 94.419176ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 435.17699ms
Throughput 229.79 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 43.674189801s
Average Latency 434.825368ms
Throughput 114.48 requests/second

@dmihalcik-virtru dmihalcik-virtru marked this pull request as ready for review April 14, 2026 19:08
@dmihalcik-virtru dmihalcik-virtru requested a review from a team as a code owner April 14, 2026 19:08
@dmihalcik-virtru dmihalcik-virtru requested review from a team as code owners April 14, 2026 19:08
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sdk/tdf.go (1)

676-686: ⚠️ Potential issue | 🟠 Major

Derive the wrap scheme from the parsed public key, not kasInfo.Algorithm.

Line 677 still trusts metadata to choose the EC/RSA path. If kasInfo.Algorithm is empty or stale while kasInfo.PublicKey is actually EC, this falls into the RSA branch, generateWrapKeyWithRSA will still encrypt with the EC encryptor returned by FromPublicPEM, and the manifest is emitted as wrapped without an EphemeralPublicKey. That key-access object is not rewrappable later.

Please branch on the parsed key/encryptor type instead, or at least fail fast when the PEM type and declared algorithm disagree.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sdk/tdf.go` around lines 676 - 686, The branch decision should be based on
the parsed public key/encryptor type rather than trusting kasInfo.Algorithm;
parse kasInfo.PublicKey (via the same flow that returns an encryptor from
FromPublicPEM) and inspect its key type (EC vs RSA) before choosing
generateWrapKeyWithEC or generateWrapKeyWithRSA, or else return an error if the
parsed key type conflicts with kasInfo.Algorithm; update the logic around
ktype/kasInfo.Algorithm, generateWrapKeyWithEC, generateWrapKeyWithRSA,
FromPublicPEM, and the keyAccess fields (KeyType, WrappedKey,
EphemeralPublicKey) so the manifest correctly records an EphemeralPublicKey for
EC keys and prevents creating non-rewrappable entries when the PEM and declared
algorithm disagree.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/ocrypto/asym_decryption_test.go`:
- Around line 136-153: The TestAsymDecryptionKeyType loop should be converted to
subtests so failures show which RSA size failed: for each bits in {RSA2048Size,
RSA4096Size} call t.Run with a descriptive name (e.g. "RSA2048"/"RSA4096" or
fmt.Sprintf("%d", bits)), capture bits in the closure, and move t.Parallel()
into the subtest body; inside the subtest keep the existing logic
(NewRSAKeyPair, PrivateKeyInPemFormat, FromPrivatePEM, type assertion to
AsymDecryption and the KeyType checks against RSA2048Key/RSA4096Key).

In `@lib/ocrypto/asym_encryption.go`:
- Around line 288-293: Define a small interface (e.g.,
EphemeralPublicKeyExporter) that declares EphemeralPublicKeyInPemFormat()
(string, error) and have ECEncryptor implicitly implement it (the method already
exists), then update the public API to return or accept that interface where
callers need to export the ephemeral PEM instead of requiring a concrete
ocrypto.ECEncryptor; ensure references to PublicKeyEncryptor remain unchanged
unless the API should explicitly include the new interface, and update call
sites to use the new EphemeralPublicKeyExporter interface for PEM export without
downcasting to ECEncryptor.

In `@lib/ocrypto/ec_key_pair.go`:
- Around line 480-488: The two exported helpers (ECPrivateKeyInPemFormat,
ECPublicKeyInPemFormat) pass value-type ecdsa.PrivateKey/ecdsa.PublicKey to
privateKeyInPemFormat which only handles pointer cases, so zero-value structs
bypass nil checks; update privateKeyInPemFormat to add switch cases for the
value types (case ecdsa.PrivateKey: and case ecdsa.PublicKey:) and perform the
same validity checks as for pointers (e.g., for ecdsa.PrivateKey verify key.D !=
nil and for ecdsa.PublicKey verify key.X != nil && key.Y != nil), returning the
same error ("failed to generate PEM formatted private key"/appropriate public
key error) when those fields are nil to prevent falling through to
x509.MarshalPKCS8PrivateKey with a zero-value.

In `@sdk/experimental/tdf/key_access.go`:
- Around line 186-201: The EC wrapper currently returns the non-canonical string
"eccWrapped" from wrapKeyWithEC; update the return to use the canonical key type
"ec-wrapped" so it matches the rest of the codebase (see wrapKeyWithEC in
key_access.go and the canonical uses in sdk/tdf.go and
lib/ocrypto/asym_encryption.go), keeping the other return values and error
handling unchanged.
- Around line 165-182: The code currently chooses the wrapping branch using
pubKeyInfo.Algorithm (ktype) even after parsing the PEM; instead, base the
decision on the parsed kasPublicKey's runtime type: after
ocrypto.FromPublicPEM(...) check if kasPublicKey implements ocrypto.ECEncryptor
(or use a type switch) and call wrapKeyWithEC(ktype, epk, symKey) when it does,
otherwise call wrapKeyWithRSA(kasPublicKey, symKey); update error paths to
report a clear mismatch if the parsed key cannot perform the expected operations
and remove reliance on pubKeyInfo.Algorithm for branching.

In `@sdk/kas_client.go`:
- Around line 196-208: In handleECKeyResponse, explicitly validate that
response.GetSessionPublicKey() is not empty before calling pem.Decode so you can
return a clearer error; check the returned string from
kas.RewrapResponse.GetSessionPublicKey(), if it's empty return a descriptive
error like "empty KAS session public key" and only then call pem.Decode,
preserving the existing session key type assertion (k.sessionKey as
ocrypto.ECDecryptor) and the subsequent call to k.processECResponse with
block.Bytes.

---

Outside diff comments:
In `@sdk/tdf.go`:
- Around line 676-686: The branch decision should be based on the parsed public
key/encryptor type rather than trusting kasInfo.Algorithm; parse
kasInfo.PublicKey (via the same flow that returns an encryptor from
FromPublicPEM) and inspect its key type (EC vs RSA) before choosing
generateWrapKeyWithEC or generateWrapKeyWithRSA, or else return an error if the
parsed key type conflicts with kasInfo.Algorithm; update the logic around
ktype/kasInfo.Algorithm, generateWrapKeyWithEC, generateWrapKeyWithRSA,
FromPublicPEM, and the keyAccess fields (KeyType, WrappedKey,
EphemeralPublicKey) so the manifest correctly records an EphemeralPublicKey for
EC keys and prevents creating non-rewrappable entries when the PEM and declared
algorithm disagree.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0a7022c7-f77c-4a72-8811-b1965976ce94

📥 Commits

Reviewing files that changed from the base of the PR and between 7fae2d7 and 0a1cba2.

📒 Files selected for processing (21)
  • .gitignore
  • lib/ocrypto/asym_decryption.go
  • lib/ocrypto/asym_decryption_test.go
  • lib/ocrypto/asym_encryption.go
  • lib/ocrypto/ec_decrypt_compressed_test.go
  • lib/ocrypto/ec_key_pair.go
  • lib/ocrypto/ec_key_pair_test.go
  • lib/ocrypto/rsa_key_pair.go
  • sdk/codegen/runner/generate.go
  • sdk/experimental/tdf/key_access.go
  • sdk/experimental/tdf/key_access_test.go
  • sdk/kas_client.go
  • sdk/kas_client_test.go
  • sdk/tdf.go
  • sdk/tdf_config.go
  • sdk/tdf_test.go
  • service/internal/security/basic_manager.go
  • service/internal/security/basic_manager_test.go
  • service/internal/security/in_process_provider.go
  • service/kas/access/rewrap.go
  • service/trust/key_manager.go

Comment thread lib/ocrypto/asym_decryption_test.go
Comment thread lib/ocrypto/asym_encryption.go
Comment thread lib/ocrypto/ec_key_pair.go
Comment thread sdk/experimental/tdf/key_access.go Outdated
Comment thread sdk/experimental/tdf/key_access.go Outdated
Comment thread sdk/kas_client.go
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 195.997392ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 112.309668ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 390.351394ms
Throughput 256.18 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 40.964373153s
Average Latency 407.790917ms
Throughput 122.06 requests/second

dmihalcik-virtru and others added 2 commits April 15, 2026 15:46
Fix incorrect/stale comments (encrypt vs decrypt, misleading deprecation
targets, stale TODOs), improve error messages to be actionable, add nil
validation to NewSaltedECDecryptor, fix value-type nil-guard bypass in
ECPrivateKeyInPemFormat/ECPublicKeyInPemFormat, and add ECIES round-trip
tests across all EC curves plus a test verifying recipient vs ephemeral
key PEM separation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Dave Mihalcik <dmihalcik@virtru.com>
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 196.378304ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 101.054599ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 399.170012ms
Throughput 250.52 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 41.923686966s
Average Latency 417.916568ms
Throughput 119.26 requests/second

@github-actions
Copy link
Copy Markdown
Contributor

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/ocrypto/asym_decryption.go (1)

233-320: ⚠️ Potential issue | 🔴 Critical

DecryptWithEphemeralKey dereferences a nil private key without a guard.

Line 241 (e.sk.ECDH) and line 313 (e.sk.Curve() in the fallback path) will panic on a zero-value ECDecryptor{} or when NewECDecryptor(nil) is called. The Public() and KeyType() methods already protect this case; this method should do the same.

🔧 Proposed fix
 func (e ECDecryptor) DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, error) {
+	if e.sk == nil {
+		return nil, errors.New("failed to decrypt, private key is empty")
+	}
 	ek, err := e.parseEphemeralPublicKey(ephemeral)
 	if err != nil {
 		return nil, fmt.Errorf("failed to parse ephemeral public key: %w", err)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/ocrypto/asym_decryption.go` around lines 233 - 320, The methods
DecryptWithEphemeralKey and parseEphemeralPublicKey can panic when the
ECDecryptor's private key (e.sk) is nil; add the same nil-check guard used in
deriveSharedKey (or Public()/KeyType()) at the start of DecryptWithEphemeralKey
and before calling e.sk.Curve() in parseEphemeralPublicKey, returning a clear
error like "failed to derive shared key, private key is empty" if e.sk == nil so
all code paths fail safely instead of dereferencing a nil pointer.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/ocrypto/asym_decryption_test.go`:
- Around line 95-102: Extend the NilKeyGuards subtest to also call
ECDecryptor{}.DecryptWithEphemeralKey(...) and assert it returns an error (and
does not panic); specifically, in the t.Run "NilKeyGuards" add a call like
nilDec.DecryptWithEphemeralKey(...) with the minimal/zero inputs used by other
tests (e.g., nil or empty byte slices for ciphertext/ephemeral public key) and
use require.Error(t, err) to ensure the zero-value ECDecryptor path that
dereferenced e.sk is covered; keep the rest of the assertions for Public() and
PrivateKeyInPemFormat() unchanged.

In `@lib/ocrypto/ec_key_pair.go`:
- Around line 237-258: Add a nil check for keyPair.PrivateKey at the start of
ECKeyPair.Decrypt, ECKeyPair.Public, and ECKeyPair.DeriveSharedKey: if
keyPair.PrivateKey == nil return a descriptive error (matching the style used in
PublicKeyInPemFormat/KeySize/KeyType and related types) instead of calling
ConvertToECDHPrivateKey(keyPair.PrivateKey) so you avoid dereferencing a nil
receiver inside ConvertToECDHPrivateKey/ k.ECDH().

In `@sdk/experimental/tdf/key_access_test.go`:
- Around line 93-100: Add a regression test to ensure wrapKeyWithPublicKey uses
the parsed PEM type, not stale pubKeyInfo.Algorithm: create an EC key via
NewECPrivateKey/ECCModeSecp256r1, derive its PEM with
Public().PublicKeyInPemFormat(), then construct a pubKeyInfo-like input where
Algorithm is bogus (e.g., "rsa:2048") and call wrapKeyWithPublicKey (or the test
helper that routes to it); assert the function follows the parsed PEM (EC
branch) and succeeds. Add the inverse case too (RSA PEM with Algorithm
"ec:secp256r1") to validate both directions; place these cases alongside the
existing EC tests in key_access_test.go and use require.NoError/require.Equal
assertions already used in the file.

In `@service/trust/key_manager.go`:
- Around line 33-35: Update the Depracation comment for DeriveKey to explicitly
state that callers should use Decrypt and that DeriveKey remains exported only
for API compatibility; note that DelegatingKeyService will forward calls but
most current key manager implementations intentionally return an
unsupported-operation error (e.g., ErrUnsupportedOperation or similar) —
document that expected behavior and the recommended migration path (call Decrypt
with the same inputs) in the comment above DeriveKey and in any public docs so
integrators are not misled; reference the DeriveKey method,
DelegatingKeyService, and the key manager implementations in the comment so
readers can locate the implementation-specific unsupported behavior.

---

Outside diff comments:
In `@lib/ocrypto/asym_decryption.go`:
- Around line 233-320: The methods DecryptWithEphemeralKey and
parseEphemeralPublicKey can panic when the ECDecryptor's private key (e.sk) is
nil; add the same nil-check guard used in deriveSharedKey (or
Public()/KeyType()) at the start of DecryptWithEphemeralKey and before calling
e.sk.Curve() in parseEphemeralPublicKey, returning a clear error like "failed to
derive shared key, private key is empty" if e.sk == nil so all code paths fail
safely instead of dereferencing a nil pointer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 685e56f0-5a60-4f54-a857-87c3aaaddcad

📥 Commits

Reviewing files that changed from the base of the PR and between 0a1cba2 and c7b0b7f.

📒 Files selected for processing (6)
  • lib/ocrypto/asym_decryption.go
  • lib/ocrypto/asym_decryption_test.go
  • lib/ocrypto/ec_key_pair.go
  • sdk/experimental/tdf/key_access.go
  • sdk/experimental/tdf/key_access_test.go
  • service/trust/key_manager.go

Comment on lines +95 to +102
t.Run("NilKeyGuards", func(t *testing.T) {
t.Parallel()
nilDec := ECDecryptor{}
_, err := nilDec.Public()
require.Error(t, err)
_, err = nilDec.PrivateKeyInPemFormat()
require.Error(t, err)
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a regression check for zero-value DecryptWithEphemeralKey.

NilKeyGuards currently misses the one EC path that still dereferences e.sk. Extending this subtest to assert an error from ECDecryptor{}.DecryptWithEphemeralKey(...) would catch the panic fixed above.

🧪 Proposed test addition
 	t.Run("NilKeyGuards", func(t *testing.T) {
 		t.Parallel()
 		nilDec := ECDecryptor{}
 		_, err := nilDec.Public()
 		require.Error(t, err)
 		_, err = nilDec.PrivateKeyInPemFormat()
 		require.Error(t, err)
+		_, err = nilDec.DecryptWithEphemeralKey(nil, nil)
+		require.Error(t, err)
 	})

As per coding guidelines, "Run go test ./... or make test and ensure all existing tests pass; add tests for new functionality".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/ocrypto/asym_decryption_test.go` around lines 95 - 102, Extend the
NilKeyGuards subtest to also call ECDecryptor{}.DecryptWithEphemeralKey(...) and
assert it returns an error (and does not panic); specifically, in the t.Run
"NilKeyGuards" add a call like nilDec.DecryptWithEphemeralKey(...) with the
minimal/zero inputs used by other tests (e.g., nil or empty byte slices for
ciphertext/ephemeral public key) and use require.Error(t, err) to ensure the
zero-value ECDecryptor path that dereferenced e.sk is covered; keep the rest of
the assertions for Public() and PrivateKeyInPemFormat() unchanged.

Comment on lines +237 to +258
func (keyPair ECKeyPair) Decrypt(data []byte) ([]byte, error) {
ecdhPrivateKey, err := ConvertToECDHPrivateKey(keyPair.PrivateKey)
if err != nil {
return nil, err
}
dec, err := NewECDecryptor(ecdhPrivateKey)
if err != nil {
return nil, err
}
return dec.Decrypt(data)
}

func (keyPair ECKeyPair) Public() (PublicKeyEncryptor, error) {
ecdhPrivateKey, err := ConvertToECDHPrivateKey(keyPair.PrivateKey)
if err != nil {
return nil, err
}
dec, err := NewECDecryptor(ecdhPrivateKey)
if err != nil {
return nil, err
}
return dec.Public()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the file structure and find the methods mentioned
cat -n lib/ocrypto/ec_key_pair.go | head -100

Repository: opentdf/platform

Length of output: 2908


🏁 Script executed:

# Get file size to understand scope
wc -l lib/ocrypto/ec_key_pair.go

Repository: opentdf/platform

Length of output: 90


🏁 Script executed:

# Look for the ConvertToECDHPrivateKey function and the methods in question
rg -n "ConvertToECDHPrivateKey|func.*Decrypt|func.*Public|func.*DeriveSharedKey" lib/ocrypto/ec_key_pair.go

Repository: opentdf/platform

Length of output: 1544


🏁 Script executed:

# Check the full implementation around lines 237-279
sed -n '237,279p' lib/ocrypto/ec_key_pair.go

Repository: opentdf/platform

Length of output: 1108


🏁 Script executed:

# Look at the ConvertToECDHPrivateKey function implementation
rg -A 15 "func ConvertToECDHPrivateKey" lib/ocrypto/

Repository: opentdf/platform

Length of output: 1004


🏁 Script executed:

# Check if there's an existing pattern of nil-checking in similar methods in this file
rg -B 3 "private key is empty" lib/ocrypto/

Repository: opentdf/platform

Length of output: 1649


🏁 Script executed:

# Check the entire function signatures and implementations
sed -n '200,350p' lib/ocrypto/ec_key_pair.go

Repository: opentdf/platform

Length of output: 4241


Add nil guards for keyPair.PrivateKey in Decrypt, Public, and DeriveSharedKey methods.

Lines 237, 249, and 269 call ConvertToECDHPrivateKey(keyPair.PrivateKey) without checking if keyPair.PrivateKey is nil. When a zero-value ECKeyPair{} is used, the nil pointer still matches the type switch, causing k.ECDH() to dereference a nil receiver and panic instead of returning an error.

This is inconsistent with other methods in the same struct (PublicKeyInPemFormat, KeySize, KeyType) and related types (ECDecryptor, AsymDecryption, RsaKeyPair), all of which guard against nil private keys.

🔧 Proposed fix
 func (keyPair ECKeyPair) Decrypt(data []byte) ([]byte, error) {
+	if keyPair.PrivateKey == nil {
+		return nil, errors.New("failed to decrypt, private key is empty")
+	}
 	ecdhPrivateKey, err := ConvertToECDHPrivateKey(keyPair.PrivateKey)
 	if err != nil {
 		return nil, err
 	}
 	dec, err := NewECDecryptor(ecdhPrivateKey)
 	if err != nil {
 		return nil, err
 	}
 	return dec.Decrypt(data)
 }

 func (keyPair ECKeyPair) Public() (PublicKeyEncryptor, error) {
+	if keyPair.PrivateKey == nil {
+		return nil, errors.New("failed to generate public key encryptor, private key is empty")
+	}
 	ecdhPrivateKey, err := ConvertToECDHPrivateKey(keyPair.PrivateKey)
 	if err != nil {
 		return nil, err
 	}
 	dec, err := NewECDecryptor(ecdhPrivateKey)
 	if err != nil {
 		return nil, err
 	}
 	return dec.Public()
 }

 func (keyPair ECKeyPair) DeriveSharedKey(publicKeyInPem string) ([]byte, error) {
+	if keyPair.PrivateKey == nil {
+		return nil, errors.New("failed to derive shared key, private key is empty")
+	}
 	ecdhPrivateKey, err := ConvertToECDHPrivateKey(keyPair.PrivateKey)
 	if err != nil {
 		return nil, err
 	}
 	dec, err := NewECDecryptor(ecdhPrivateKey)
 	if err != nil {
 		return nil, err
 	}
 	return dec.deriveSharedKey(publicKeyInPem)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/ocrypto/ec_key_pair.go` around lines 237 - 258, Add a nil check for
keyPair.PrivateKey at the start of ECKeyPair.Decrypt, ECKeyPair.Public, and
ECKeyPair.DeriveSharedKey: if keyPair.PrivateKey == nil return a descriptive
error (matching the style used in PublicKeyInPemFormat/KeySize/KeyType and
related types) instead of calling ConvertToECDHPrivateKey(keyPair.PrivateKey) so
you avoid dereferencing a nil receiver inside ConvertToECDHPrivateKey/ k.ECDH().

Comment on lines +93 to 100
ecPrivateKey, err := ocrypto.NewECPrivateKey(ocrypto.ECCModeSecp256r1)
require.NoError(t, err, "Should generate EC private key")

ecPublicKeyPEM, err := ecKeyPair.PublicKeyInPemFormat()
ecPublicKey, err := ecPrivateKey.Public()
require.NoError(t, err, "Should derive EC public key")

ecPublicKeyPEM, err := ecPublicKey.PublicKeyInPemFormat()
require.NoError(t, err, "Should get public key in PEM format")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a regression case for stale Algorithm metadata.

These updated EC tests still use matching Algorithm + PEM pairs, so they would not catch a regression where wrapKeyWithPublicKey starts routing off pubKeyInfo.Algorithm again. Please add at least one case with an EC PEM plus Algorithm: "rsa:2048" (and/or the inverse) and assert the branch still follows the parsed PEM type.

As per coding guidelines **/*.go: Run go test ./... or make test and ensure all existing tests pass; add tests for new functionality.

Also applies to: 112-112, 403-410, 423-423

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sdk/experimental/tdf/key_access_test.go` around lines 93 - 100, Add a
regression test to ensure wrapKeyWithPublicKey uses the parsed PEM type, not
stale pubKeyInfo.Algorithm: create an EC key via
NewECPrivateKey/ECCModeSecp256r1, derive its PEM with
Public().PublicKeyInPemFormat(), then construct a pubKeyInfo-like input where
Algorithm is bogus (e.g., "rsa:2048") and call wrapKeyWithPublicKey (or the test
helper that routes to it); assert the function follows the parsed PEM (EC
branch) and succeeds. Add the inverse case too (RSA PEM with Algorithm
"ec:secp256r1") to validate both directions; place these cases alongside the
existing EC tests in key_access_test.go and use require.NoError/require.Equal
assertions already used in the file.

Comment on lines +33 to 35
//
// Deprecated: Directly use Decrypt when appropriate.
DeriveKey(ctx context.Context, key KeyDetails, ephemeralPublicKeyBytes []byte, curve elliptic.Curve) (ProtectedKey, error)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Deprecation guidance is too vague for an active public method.

Line 34 suggests migrating to Decrypt, but DeriveKey is still callable through DelegatingKeyService and current managers return unsupported operation. Please document that behavior explicitly to prevent misleading integrations.

Suggested doc tweak
 // DeriveKey computes an agreed upon secret key derived from an ECDH exchange.
 //
-// Deprecated: Directly use Decrypt when appropriate.
+// Deprecated: This method is being phased out and may return "unsupported operation"
+// in key manager implementations. Prefer the Decrypt-based unwrap flow where applicable.
 DeriveKey(ctx context.Context, key KeyDetails, ephemeralPublicKeyBytes []byte, curve elliptic.Curve) (ProtectedKey, error)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@service/trust/key_manager.go` around lines 33 - 35, Update the Depracation
comment for DeriveKey to explicitly state that callers should use Decrypt and
that DeriveKey remains exported only for API compatibility; note that
DelegatingKeyService will forward calls but most current key manager
implementations intentionally return an unsupported-operation error (e.g.,
ErrUnsupportedOperation or similar) — document that expected behavior and the
recommended migration path (call Decrypt with the same inputs) in the comment
above DeriveKey and in any public docs so integrators are not misled; reference
the DeriveKey method, DelegatingKeyService, and the key manager implementations
in the comment so readers can locate the implementation-specific unsupported
behavior.

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 191.528464ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 99.44597ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 410.675248ms
Throughput 243.50 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 44.295885345s
Average Latency 441.193746ms
Throughput 112.88 requests/second

@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Govulncheck found vulnerabilities ⚠️

The following modules have known vulnerabilities:

  • examples
  • sdk
  • service
  • lib/fixtures
  • tests-bdd

See the workflow run for details.

@dmihalcik-virtru dmihalcik-virtru marked this pull request as draft April 20, 2026 16:50
@dmihalcik-virtru
Copy link
Copy Markdown
Member Author

I'm moving this to draft since it is too big and covers too much ground. I'll sequence some of the useful changes out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:kas Key Access Server comp:lib:ocrypto comp:sdk A software development kit, including library, for client applications and inter-service communicati pqc size/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant