Skip to content

fix(cryptography): skip KDF-iterations floor on decrypt path [STUD-80534]#577

Open
alexandru-petre wants to merge 1 commit into
developfrom
feature/STUD-80534-decrypt-kdf-floor
Open

fix(cryptography): skip KDF-iterations floor on decrypt path [STUD-80534]#577
alexandru-petre wants to merge 1 commit into
developfrom
feature/STUD-80534-decrypt-kdf-floor

Conversation

@alexandru-petre

Copy link
Copy Markdown
Collaborator

Context

The Cryptography package's symmetric encrypt/decrypt activities (EncryptText/File, DecryptText/File) and the coded-workflow CryptographyService all route through SymmetricInteropHelper, which validates cross-property invariants before dispatching to CryptographyHelper. One invariant is a MinKdfIterations = 1000 floor on the PBKDF2 iteration count — part of the third-party interop work (STUD=64429 → STUD=80231) that introduced the OpenSslEnc wire format.

Problem Statement

The 1000-iteration floor was enforced on both encrypt and decrypt. On decrypt this is wrong: a third-party blob produced with a low iteration count (e.g. openssl enc -pbkdf2 -iter 100 -md sha256 -salt -k <pw>) is mathematically decryptable — the producer chose 100, we can derive the matching key/IV — but the package threw Validation_KdfIterations_BelowMinimum before reaching the decrypt code. This defeats the headline interop premise of OpenSslEnc for anyone consuming low-iteration data.

Analysis

RunSymmetricWithKeyLifecycle (and CryptographyService.ValidateSymmetric) called the single validator with no direction context, so the floor — correct only on encrypt, where it prevents emitting weak ciphertext — also gated decrypt.

Behavior Before This PR

Decrypting an OpenSslEnc blob produced at iter=100 with KdfIterations=100 throws ArgumentException (Validation_KdfIterations_BelowMinimum) before any decryption is attempted, even though the key/IV can be derived exactly.

Behavior After This PR

The same decrypt succeeds and returns the plaintext. Encrypt with KdfIterations=100 still throws (floor preserved); negative iterations are still rejected on both paths; and KdfIterations=0 still resolves to the format default on both paths.

Implementation

A bool isDecrypt flag (optional, defaults to false) is threaded through ValidateInteropSettings and RunSymmetricWithKeyLifecycle; only the positive-but-below-1000 branch is gated on !isDecrypt. The negative-iteration rejection is deliberately left unconditional. The optional default keeps all existing source callers source-compatible (the helper is documented as package-internal glue).

How to Test

  • dotnet test Activities/Activities.Cryptography.sln — full suite green (784 + 123).
  • Reproducer: dotnet test --filter "FullyQualifiedName~OpenSslEnc_AesCbc_DecryptHonoursLowKdfIterations" fails on develop (ArgumentException) and passes on this branch.
  • Companion pins: OpenSslEnc_AesCbc_EncryptStillRefusesLowKdfIterations, OpenSslEnc_AesCbc_NegativeKdfIterations_RejectedOnBothDirections, and the Validate_KdfIterations_AtFloor_DecryptSkipsPositiveFloor theory.

…534]

The MinKdfIterations=1000 floor in SymmetricInteropHelper.ValidateInteropSettings
applied to both encrypt and decrypt. On decrypt it wrongly blocked legitimate
third-party blobs produced with a low iteration count (e.g. openssl enc -iter 100),
which are mathematically decryptable.

Thread an isDecrypt flag through ValidateInteropSettings and
RunSymmetricWithKeyLifecycle (and CryptographyService.ValidateSymmetric for the
coded-workflow path); skip only the positive-but-below-1000 floor on decrypt.
Encrypt-side floor, negative rejection, and zero-means-default are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alexandru-petre alexandru-petre marked this pull request as ready for review June 19, 2026 20:04
@alexandru-petre alexandru-petre requested a review from Copilot June 19, 2026 20:09
@alexandru-petre alexandru-petre self-assigned this Jun 19, 2026
@alexandru-petre alexandru-petre requested a review from viogroza June 19, 2026 20:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts the Cryptography package’s symmetric interop validation so that the MinKdfIterations = 1000 floor is enforced only on encrypt, not on decrypt, enabling successful decryption of third‑party OpenSslEnc payloads produced with low PBKDF2 iteration counts while preserving the encrypt-side guardrail.

Changes:

  • Thread an isDecrypt flag through SymmetricInteropHelper.ValidateInteropSettings / RunSymmetricWithKeyLifecycle and skip the positive-below-floor iteration check on decrypt.
  • Update decrypt activity call sites (DecryptText/DecryptFile) and coded-workflow CryptographyService to pass isDecrypt: true on decrypt validation paths.
  • Add/extend tests to pin decrypt-accepts-low-iterations behavior while keeping encrypt refusal and negative-iteration rejection.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Activities/Cryptography/UiPath.Cryptography/SymmetricInteropHelper.cs Adds isDecrypt direction context to validation and lifecycle helper to skip the encrypt-only iteration floor during decrypt.
Activities/Cryptography/UiPath.Cryptography.Activities/DecryptText.cs Passes isDecrypt: true when running symmetric decrypt lifecycle.
Activities/Cryptography/UiPath.Cryptography.Activities/DecryptFile.cs Passes isDecrypt: true when running symmetric decrypt lifecycle.
Activities/Cryptography/UiPath.Cryptography.Activities.Tests/SymmetricInteropHelperTests.cs Adds validator theory ensuring decrypt skips the positive iteration floor while negatives still throw.
Activities/Cryptography/UiPath.Cryptography.Activities.Tests/ExternalInteropInProcessTests.cs Adds interop regression tests covering decrypting low-iteration OpenSslEnc blobs and ensuring encrypt still refuses.
Activities/Cryptography/UiPath.Cryptography.Activities.API/Services/CryptographyService.cs Plumbs decrypt/encrypt direction into the service’s symmetric validation path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sonarqubecloud

Copy link
Copy Markdown

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.

2 participants