Skip to content

Fix exception handling in Open()#24

Merged
mtmk merged 4 commits intomainfrom
fix-open-exception-handling
Apr 7, 2026
Merged

Fix exception handling in Open()#24
mtmk merged 4 commits intomainfrom
fix-open-exception-handling

Conversation

@mtmk
Copy link
Copy Markdown
Member

@mtmk mtmk commented Mar 31, 2026

Open() had two issues: short ciphertext (29-43 bytes) passed the length check but caused OverflowException from a negative array allocation in TweetNaCl, and auth failures threw InvalidCipherTextException (not a subclass of NKeysException) so callers catching NKeysException would miss decryption errors. Tightened the minimum input length and wrapped the TweetNaCl call to normalize exceptions.

  • Open_rejects_short_input (0, 28, 29, 43 bytes all throw NKeysException)
  • DecodePubCurveKey_blackbox_tampered_ciphertext_fails (tampered ciphertext throws NKeysException)
  • DecodePubCurveKey_blackbox_wrong_sender_fails_open (wrong sender throws NKeysException)
  • DecodePubCurveKey_blackbox_wrong_receiver_fails_open (wrong receiver throws NKeysException)

mtmk added 2 commits March 31, 2026 11:50
Two issues: (1) short ciphertext (29-43 bytes) passes the
length check but causes OverflowException inside TweetNaCl
from a negative array allocation. Tighten the minimum to
require BoxBoxZeroBytes (16) after the header. (2) Auth
failures throw InvalidCipherTextException which extends
Exception, not NKeysException, so callers catching
NKeysException miss decryption errors. Wrap the TweetNaCl
call to normalize all exceptions to NKeysException.
Tighten three existing tests from ThrowsAny<Exception> to
Throws<NKeysException> now that Open() normalizes exceptions.
Add a theory test verifying short inputs (0, 28, 29, 43 bytes)
are rejected with NKeysException.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 hardens KeyPair.Open() for Curve (xkey) decryption by preventing short ciphertexts from reaching TweetNaCl in a way that can trigger runtime exceptions, and by normalizing decryption/authentication failures to NKeysException so callers can reliably catch NKeys-specific failures.

Changes:

  • Tightened the minimum sealed payload length check in Open() to include NaCl box overhead.
  • Wrapped the TweetNaCl CryptoBoxOpen call to convert non-NKeysException failures into NKeysException.
  • Updated/added tests to assert NKeysException for wrong sender/receiver, tampering, and short inputs.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
NATS.NKeys/KeyPair.cs Strengthens input validation and wraps TweetNaCl exceptions during Open() to normalize error types.
NATS.NKeys.Tests/NKeysTest.cs Adjusts existing blackbox tests to expect NKeysException and adds coverage for short-input rejection.

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

Comment thread NATS.NKeys/KeyPair.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@mtmk mtmk requested a review from aricart April 2, 2026 08:16
Comment thread NATS.NKeys/KeyPair.cs Outdated
}
catch (TweetNaCl.NKeyNaclException)
{
throw new NKeysException("Decryption failed");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

wouldn't it be useful to also know what the actual error was from the underlying library?

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.

good point. I can add it as inner

Copy link
Copy Markdown
Member

@aricart aricart left a comment

Choose a reason for hiding this comment

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

LGTM - but possibly better to let the caller know why it failed- it may have the key length, or something corrupt, etc.

Pass the caught NKeyNaclException as InnerException so callers
can inspect the underlying failure reason.
@mtmk mtmk merged commit 8f2c620 into main Apr 7, 2026
8 checks passed
@mtmk mtmk deleted the fix-open-exception-handling branch April 7, 2026 11:02
@mtmk mtmk mentioned this pull request Apr 7, 2026
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.

3 participants