Skip to content

fix(dashcore): reject high-S signatures in verify_data_signature - #1379

Merged
xdustinface merged 2 commits into
devfrom
fix/reject-high-s-signatures
Nov 12, 2026
Merged

xdustinface merged 2 commits into
devfrom
fix/reject-high-s-signatures

Conversation

@ZocoLini

@ZocoLini ZocoLini commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Since the Base SDK bump in #1214, EcdsaPublicKey::verify normalizes S before verifying, so verify_data_signature silently started accepting high-S ECDSA signatures. A high-S signature is a malleable twin of the low-S one, and callers relying on the previous strict behavior lost it without notice.

verify_data_signature now checks is_low_s before verifying and rejects high-S signatures, restoring the behavior from before the bump.

Closes #1249.

PR Hygiene · 9b1df99

  • Bots — coderabbitai skipped after its own rate limit
  • Self-review — post /self-reviewed
  • Build running
  • Approvals
    • files with no dedicated owner (dash/src/signer.rs) — QuantumExplorer or xdustinface

When every merge requirement is met, the PR Hygiene check passes. Reviewer limits do not block merging; other required GitHub checks and protections still apply.

Summary by CodeRabbit

  • Bug Fixes
    • Signatures with high S values are now rejected, preventing acceptance of malleable signature variants.

Since the Base SDK bump in #1214, `EcdsaPublicKey::verify` normalizes S before verifying, so `verify_data_signature` accepted high-S signatures it refused before. A high-S signature is a malleable twin of the low-S one.

`verify_data_signature` now checks `is_low_s` before verifying and returns an error for a high-S signature, as it did before the bump.
@coderabbitai

coderabbitai Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 52 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 352f99c and 9b1df99.

Files selected for processing: 1

  • dash/src/signer.rs

No actionable comments were generated in the recent review.

Walkthrough

verify_data_signature now rejects signatures with a high S value before public-key verification. Its documentation describes the rejection as protection against malleable twins of low-S signatures.

Changes: Signature verification

Layer / File(s) Summary
Document and enforce low-S verification
dash/src/signer.rs
The function documentation now states that high-S signatures are rejected. The implementation returns "the signature has a high S value" for a high-S signature and verifies low-S signatures as before.

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

  • dashpay/rust-dashcore#1214: Changed the Base SDK-backed verification behavior to accept high-S signatures and exposed the low-S check used here.

Suggested reviewers: xdustinface, quantumexplorer

Merge Risk: Minimal · previous review 352f9

The verifier rejects high-S signatures as intended; no merge-blocking issue was identified.

Pre-merge checks: Passed 5

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main change: rejecting high-S signatures in verify_data_signature.
Linked Issues check Passed Issue #1249 requests restoring strict low-S verification or documenting the changed behavior. verify_data_signature now checks sig.is_low_s() and returns an error before public-key verification fo…
Out of Scope Changes check Passed The whole-PR diff changes only dash/src/signer.rs. The low-S check and its documentation directly address issue #1249. No unrelated changes are present.
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Full details: Linked Issues check

Explanation

Issue #1249 requests restoring strict low-S verification or documenting the changed behavior. verify_data_signature now checks sig.is_low_s() and returns an error before public-key verification for high-S signatures. Its documentation also states that high-S signatures are rejected. The change implements the strict-verification option. The issue does not require a new automated test.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 1 files.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between ee50584 and 352f99c.

Files selected for processing: 1

  • dash/src/signer.rs

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@github-actions

github-actions Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Waiting for bot review — coderabbitai not yet. Wait for the missing reviews, or a writer can post /skip-bots to proceed without them; blocking findings still need addressing.
Full checklist in the description.

@github-actions github-actions Bot added the waiting-bots Waiting for the review bots to report on this head label Nov 9, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Nov 9, 2026
@github-actions

github-actions Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Bots are done — your move: address manki-review[bot] requested changes, then post /self-reviewed.
Full checklist in the description.

@github-actions github-actions Bot added waiting-self-review Waiting for the author to post /self-reviewed and removed waiting-bots Waiting for the review bots to report on this head labels Nov 9, 2026
@codecov

codecov Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.67%. Comparing base (ee50584) to head (9b1df99).
⚠️ Report is 12 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #1379      +/-   ##
==========================================
+ Coverage   85.60%   85.67%   +0.06%     
==========================================
  Files         268      268              
  Lines       69915    70321     +406     
==========================================
+ Hits        59853    60248     +395     
- Misses      10062    10073      +11     
Flag Coverage Δ
core 82.81% <100.00%> (+<0.01%) ⬆️
rpc 52.10% <ø> (ø)
spv 94.38% <ø> (+0.04%) ⬆️
wallet 83.53% <ø> (ø)
Files with missing lines Coverage Δ
dash/src/signer.rs 100.00% <100.00%> (ø)

... and 26 files with indirect coverage changes

@manki-review

manki-review Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

✅ Review complete in 2m 6s

Planner (5s)
    fix · 6 lines · 2 agents
    judge effort: medium

Review (security · pair): 2 findings
    ✅ Claude Sonnet 5.5 · high: 1 finding (11s)
    ✅ Claude Opus 5.5 · high: 1 finding (47s)

Judge: 1 kept · 1 dropped (49s)
    kept: 1 blocker
    dropped: 1 suggestion

Review metadata

Config:

  • Models: reviewer=claude-sonnet-5-5, judge=claude-opus-5-5
  • Triage: trivial=false, subtle=true, paired=true (planner, security-sensitive paths)
  • Team: Claude Sonnet 5.5 · high, Claude Opus 5.5 · high
  • Memory: enabled (central)

Account limits:

  • Claude subscription: weekly 82% (resets 2026-11-17 05:00 UTC)

Judge decisions:

  • Kept: "No regression test for the high-S rejection" (suggestion, high confidence): "suggestion. Missing test coverage is a suggestion under the rubric, even though AGENTS.md asks every fix to come with a regression test that fails without it. The claim holds: the diff adds only the check at dash/src/signer.rs:28 and no test. The listed uses at dash/src/signer.rs:124-186 all verify signatures produced by the normal signing path, which yields low-S, so deleting line 28 would leave them passing."

Timing:

  • Parse: 4.9s
  • Review agents: 72.1s
  • Judge: 49.1s
  • Total: 126.0s

manki-review[bot]
manki-review Bot previously requested changes Nov 11, 2026

@manki-review manki-review Bot 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.

🔴 Changes requested: 1 blocker.

Caution

Claude subscription has used 82% of its weekly limit, past the 80% mark. It resets 2026-11-17 05:00 UTC.

Once a limit is used up, reviews on that account stop until it resets.

What blocks: verify_data_signature now refuses signatures it used to accept, but no test passes it a high-S signature. Nothing shows the new check fires.

About this review
  • Reviewed 352f99c, round 1
  • 6 changed lines read in 2m 6s
  • Found by claude-sonnet-5-5 and claude-opus-5-5, judged by claude-opus-5-5
  • Tokens: 393k in (303k from cache) · 9k out · about $0.59 at API prices
  • How Manki reviews

Comment thread dash/src/signer.rs Resolved
@github-actions

github-actions Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Waiting for bot review — coderabbitai not yet. Wait for the missing reviews, or a writer can post /skip-bots to proceed without them; blocking findings still need addressing.
Full checklist in the description.

@github-actions github-actions Bot added waiting-bots Waiting for the review bots to report on this head and removed waiting-self-review Waiting for the author to post /self-reviewed labels Nov 12, 2026
@manki-review

manki-review Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

✅ Review complete in 1m 47s

Planner (4s)
    feat · 20 lines · 2 agents
    judge effort: medium

Review (security · pair): 0 findings
    ✅ Claude Sonnet 5.5 · high: 0 findings (15s)
    ✅ Claude Opus 5.5 · high: 0 findings (34s)

Judge: 0 kept · 0 dropped (38s)

Review metadata

Config:

  • Models: reviewer=claude-sonnet-5-5, judge=claude-opus-5-5
  • Triage: trivial=false, subtle=true, paired=true (planner, security-sensitive paths)
  • Team: Claude Sonnet 5.5 · high, Claude Opus 5.5 · high
  • Memory: enabled (central)

Account limits:

  • Claude subscription: weekly 45% (resets 2026-11-17 05:00 UTC)

Timing:

  • Parse: 9.6s
  • Review agents: 58.6s
  • Judge: 38.3s
  • Total: 106.6s

Last reviewed 9b1df99 · head 9b1df99 · up to date

  • Pause automatic reviews
  • Review again
  • Deeper review

@manki-review manki-review Bot 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.

✅ Approved.

What this does: Signature checking accepted a modified copy of a valid signature (the "high-S" form). Both forms are valid for the same data, so a signature could be altered without the key.


What to test

The review model wrote these steps. Check what a step runs before you follow it.

  1. Sign data with sign and check it with verify_data_signature using the compressed public key. Expect Ok(()).
  2. Replace S in that signature with n - S, the curve order minus S. Pass it to verify_data_signature. Expect an error containing the signature has a high S value.
  3. Check a normal low-S signature against an uncompressed public key. Expect Ok(()).
  4. Check a valid low-S signature against different data. Expect signature verification failed, not the high-S error.
  5. Pass a 64-byte signature with no recovery byte. Expect length not 65 bytes.
About this review
  • Reviewed 9b1df99, round 2
  • 20 changed lines read in 1m 47s
  • Found by claude-sonnet-5-5 and claude-opus-5-5, judged by claude-opus-5-5
  • Tokens: 289k in (184k from cache) · 9k out · about $0.63 at API prices
  • How Manki reviews

@manki-review
manki-review Bot dismissed their stale review November 12, 2026 12:09

Superseded by new review

@github-actions

Copy link
Copy Markdown
Contributor

Bots are done — your move: post /self-reviewed.
Full checklist in the description.

@github-actions github-actions Bot added waiting-self-review Waiting for the author to post /self-reviewed bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. and removed waiting-bots Waiting for the review bots to report on this head labels Nov 12, 2026
@xdustinface
xdustinface merged commit 21e9e94 into dev Nov 12, 2026
46 of 48 checks passed
@xdustinface
xdustinface deleted the fix/reject-high-s-signatures branch November 12, 2026 14:50
manki-review Bot added a commit to manki-review/review-memory that referenced this pull request Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. waiting-self-review Waiting for the author to post /self-reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

verify_data_signature accepts high-S ECDSA signatures since the Base SDK bump (#1214)

2 participants