Skip to content

feat(xmldsig): compute signing reference digests#79

Open
polaz wants to merge 3 commits into
mainfrom
feat/#78-signing-reference-digests
Open

feat(xmldsig): compute signing reference digests#79
polaz wants to merge 3 commits into
mainfrom
feat/#78-signing-reference-digests

Conversation

@polaz

@polaz polaz commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

  • Add signing-side reference digest computation for XMLDSig templates.
  • Add SignContext with sign_template() and sign_with_builder() for full template signing.
  • Add RustCrypto signing key adapters for RSA PKCS#1 v1.5 and ECDSA P-256/P-384 PKCS#8 private keys.
  • Fill <DigestValue>, reparse/canonicalize <SignedInfo>, sign canonical bytes, and fill <SignatureValue>.
  • Keep verification parsing strict: empty <DigestValue> is accepted only by the signing-template path.
  • Use fallible signing APIs; RSA PKCS#1 v1.5 signing uses randomized private-key operations with SysRng for blinding.
  • Cover same-document, multiple-reference, enveloped-signature, missing-URI, SHA-1 rejection, RSA-SHA256 round-trip, ECDSA-P256 round-trip, and ECDSA-P384 round-trip paths.
  • Update p384 from 0.14.0-rc.15 to stable 0.14.
  • Update README status for template signing support.

Testing

  • cargo check --all-features
  • cargo fmt -- --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo nextest run --all-features -E 'binary(signing_digest)' — 8 passed
  • cargo nextest run --all-features — 528 passed
  • cargo test --doc --all-features — 3 passed

Closes #78

- Add signing-template digest computation and fill APIs

- Preserve strict verification parsing for populated DigestValue

- Cover same-document, multi-reference, enveloped, and SHA-1 rejection cases

- Update p384 to stable 0.14

Closes #78
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added XMLDSig signing support, including filling digest values and producing signatures in signed XML.
    • Expanded key support for RSA and ECDSA signing, including P-256 and P-384.
    • Improved handling of multiple reference digests and whole-document signatures.
  • Bug Fixes

    • Strengthened validation for signature templates and reference entries.
    • Prevented unsupported digest algorithms from being used in signing flows.
  • Documentation

    • Updated the project status to reflect that XMLDSig signing is now available.

Walkthrough

Adds XMLDSig signing-side reference digest computation, template signing with RSA/ECDSA keys, public API exposure, and tests. The README and Cargo feature set are updated to reflect the signing pipeline and its optional dependency.

Changes

Signing template pipeline

Layer / File(s) Summary
Module setup and types
src/xmldsig/sign.rs, Cargo.toml
Adds signing module imports/docs, public digest and signing error/data types, and the crypto-common optional dependency wired into xmldsig.
Signing key implementations
src/xmldsig/sign.rs
Implements RSA, ECDSA P-256, and ECDSA P-384 signing keys with PKCS#8 PEM/DER constructors and algorithm-specific signing.
Template parsing helpers
src/xmldsig/sign.rs
Adds SignedInfo/Reference parsing, XMLDSig element validation, canonicalization scoping, and PKCS#8 PEM parsing helpers.
Reference digest computation
src/xmldsig/sign.rs
Computes signing-template reference digests, applies transforms, and fills <DigestValue> nodes in document order.
Template signing flow
src/xmldsig/sign.rs
Adds SignContext methods that fill digests, canonicalize <SignedInfo>, sign with the selected key, and write <SignatureValue>.
Public API exposure and docs
src/xmldsig/mod.rs, README.md
Exports the new signing module and helpers from the XMLDSig API and updates README feature/status text for signing.
Signing digest tests
tests/signing_digest.rs
Adds tests for digest filling, ordering, error cases, and RSA/ECDSA sign-and-verify round trips.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • structured-world/xml-sec#20: Introduces the XMLDSig digest/transform/reference parsing path that this PR reuses for signing-side reference digest computation.
  • structured-world/xml-sec#74: Adds the SignatureBuilder API that SignContext::sign_with_builder consumes to build and sign templates.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: computing signing-side XMLDSig reference digests.
Description check ✅ Passed The description is clearly related to the XMLDSig signing and digest changes in the PR.
Linked Issues check ✅ Passed The implementation matches #78: it computes signing digests, preserves order, keeps verification strict, rejects SHA-1, and updates p384.
Out of Scope Changes check ✅ Passed The added signing API, tests, README updates, and dependency bump are all aligned with the stated XMLDSig signing work.
Docstring Coverage ✅ Passed Docstring coverage is 91.67% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#78-signing-reference-digests

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.

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds XMLDSig template signing support. The main changes are:

  • Signing-side reference digest computation and DigestValue filling.
  • SignContext APIs for signing existing templates or builder-generated templates.
  • RSA PKCS#1 v1.5 and ECDSA P-256/P-384 PKCS#8 signing key adapters.
  • Tests for same-document references, multiple references, enveloped signatures, SHA-1 rejection, and RSA/ECDSA round trips.
  • README and public export updates for the new signing APIs.

Confidence Score: 5/5

The reviewed changed-code paths appear safe to merge.

The signing flow reuses existing dereference, transform, and canonicalization behavior and includes round-trip coverage for the new key paths. No new actionable correctness or security issues were identified in the reviewed changes.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • The signing_digest test suite was executed with cargo test --test signing_digest --all-features in the repository and completed with 8 passed and 0 failed (exit code 0).
  • The project was checked with cargo check --all-features and completed successfully with exit code 0.
  • Since cargo-nextest was unavailable as indicated by the runtime hint, a fallback Cargo test was executed.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
Cargo.toml Adds crypto-common and updates XMLDSig crypto feature wiring.
src/xmldsig/sign.rs Adds signing digest computation, full template signing, and RSA/ECDSA PKCS#8 signing key adapters.
tests/signing_digest.rs Adds coverage for digest filling, signing policy rejection, and RSA/ECDSA signing round trips.
src/xmldsig/mod.rs Exports the new XMLDSig signing APIs.
README.md Documents the new template signing and signing key support.

Reviews (3): Last reviewed commit: "fix(xmldsig): harden signing key operati..." | Re-trigger Greptile

Comment thread Cargo.toml
- Add SignContext for template and builder-based signing

- Add RSA PKCS1v15 and ECDSA P-256/P-384 signing keys

- Fill SignatureValue after SignedInfo canonicalization

- Verify RSA-SHA256 and ECDSA-P256 signing round trips
@polaz

polaz commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@polaz

polaz commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/xmldsig/sign.rs`:
- Around line 178-192: The RSA signing paths in SignatureAlgorithm::RsaSha256,
SignatureAlgorithm::RsaSha384, and SignatureAlgorithm::RsaSha512 currently use
the non-randomized pkcs1v15::SigningKey::sign flow, which may skip blinding on
the private-key operation. Update the signing logic in src/xmldsig/sign.rs to
use the randomized signing API (RandomizedSigner::try_sign_with_rng with a
secure RNG) for the RSA variants, and verify that this still preserves the
expected PKCS#1 v1.5 signature output interoperability.
- Around line 177-197: The signing flow in `Signer::sign` currently uses the
infallible `sign` method for RSA, which can panic on real failures; update the
`SignatureAlgorithm::RsaSha256`, `RsaSha384`, and `RsaSha512` branches to use
`try_sign` and propagate errors. Add a `SigningFailed` variant to
`SigningKeyError` so failures are returned instead of unwrapping, and apply the
same `try_sign`-based error handling in the ECDSA signing paths for consistency.

In `@tests/signing_digest.rs`:
- Around line 175-203: Add a round-trip test for the publicly exported
EcdsaP384SigningKey to close the coverage gap: mirror the existing
signs_ecdsa_p256_template_and_verifies_round_trip test, but use the P-384 key
fixtures, SignatureAlgorithm::EcdsaP384Sha384, and the same
SignContext::new/sign_with_builder plus verify_signature_with_pem_key flow. Keep
the assertions consistent so the new test validates that the P-384 signing and
verification pipeline works end to end.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7064a3a1-ff6f-403c-a110-3b9d1b0eeadd

📥 Commits

Reviewing files that changed from the base of the PR and between 4cece9e and 366b795.

📒 Files selected for processing (4)
  • Cargo.toml
  • src/xmldsig/mod.rs
  • src/xmldsig/sign.rs
  • tests/signing_digest.rs

Comment thread src/xmldsig/sign.rs
Comment thread src/xmldsig/sign.rs Outdated
Comment thread tests/signing_digest.rs
- Use randomized RSA PKCS1v15 signing with SysRng

- Propagate signing failures instead of using infallible sign

- Add P-384 signing round-trip coverage

- Update README signing status
@polaz

polaz commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Cargo.toml`:
- Line 34: The xmldsig dependency on crypto-common is missing the getrandom
feature, which prevents crypto_common::getrandom::SysRng from compiling in
src/xmldsig/sign.rs. Update the crypto-common entry in Cargo.toml to enable the
getrandom feature alongside dep:crypto-common so the SysRng path is available
when xmldsig is built.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 61e329c0-b360-4907-a0d1-c078f131c146

📥 Commits

Reviewing files that changed from the base of the PR and between 366b795 and 0f66d59.

📒 Files selected for processing (4)
  • Cargo.toml
  • README.md
  • src/xmldsig/sign.rs
  • tests/signing_digest.rs

Comment thread Cargo.toml
x509-parser = { version = "0.18", features = ["verify"], optional = true }
der = { version = "0.8", optional = true }
crypto-bigint = { version = "0.7", optional = true }
crypto-common = { version = "0.2", optional = true }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify the manifest enables crypto-common's getrandom feature when SysRng is imported.
rg -n 'crypto_common::getrandom::SysRng|crypto-common|getrandom' src Cargo.toml

Repository: structured-world/xml-sec

Length of output: 328


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Cargo.toml ==\n'
cat -n Cargo.toml | sed -n '1,120p'

printf '\n== src/xmldsig/sign.rs ==\n'
cat -n src/xmldsig/sign.rs | sed -n '1,220p'

Repository: structured-world/xml-sec

Length of output: 11911


🌐 Web query:

crypto-common 0.2 SysRng getrandom feature Cargo.toml.orig

💡 Result:

In the crypto-common crate (specifically version 0.2 and later), the getrandom feature enables the usage of the getrandom crate, specifically leveraging its SysRng type [1][2]. This integration replaced older, vendored random number generator implementations within crypto-common [2]. The SysRng type, introduced in getrandom v0.4, acts as the system's preferred random number source, providing a cross-platform interface for retrieving cryptographically secure random data [3]. Within the Cargo.toml of crypto-common 0.2.x, this is configured as an optional dependency: getrandom = { version = "0.4", optional = true, features = ["sys_rng"] } And defined in the [features] section: getrandom = ["rand_core", "dep:getrandom"] When the getrandom feature is enabled in your project, it allows cryptographic traits within crypto-common to utilize SysRng for operations requiring entropy, such as key generation [2][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect any Cargo.lock entry and feature wiring for crypto-common.
rg -n '^name = "crypto-common"|^version = |getrandom|SysRng' Cargo.lock Cargo.toml src -n

Repository: structured-world/xml-sec

Length of output: 3367


🌐 Web query:

crypto-common 0.2 SysRng feature getrandom site:docs.rs

💡 Result:

In the crypto-common crate version 0.2, the getrandom feature enables integration with the getrandom crate, providing access to the system's ambient cryptographically secure random number generator [1][2]. Key details regarding this feature include: Integration: When the getrandom feature is enabled, the crypto-common crate re-exports the getrandom crate [3]. This allows developers to utilize system-provided randomness directly within cryptographic workflows [2]. Functionality: Enabling this feature grants access to the Generate trait's ambient generation methods, specifically try_generate and generate [2]. These methods allow types that implement Generate to be randomly initialized using the system's preferred entropy source without requiring the user to manually pass a random number generator (RNG) instance [2]. Usage Note: The generate method will panic if the system's ambient RNG experiences an internal failure, whereas try_generate returns a Result to handle such errors gracefully [2]. The SysRng mentioned in your query refers to the interface provided by the getrandom crate (which crypto-common facilitates) to interact with the system's primary random source [4]. As of version 0.2, usage of these features is the recommended approach for secure random generation, replacing older, now-deprecated methods that relied solely on passing an explicit CryptoRng [5][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== crypto-common lock entries ==\n'
awk '
  $0 ~ /^name = "crypto-common"$/ {show=1; start=NR-2}
  show {print NR ":" $0}
  show && $0 == "" {count++; if (count >= 2) exit}
' Cargo.lock

printf '\n== surrounding packages that depend on crypto-common ==\n'
python3 - <<'PY'
from pathlib import Path
text = Path("Cargo.lock").read_text().splitlines()
for i, line in enumerate(text):
    if line.strip() == 'name = "crypto-common"':
        for j in range(max(0, i-5), min(len(text), i+30)):
            print(f"{j+1}:{text[j]}")
        print("----")
PY

Repository: structured-world/xml-sec

Length of output: 1717


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== manifest features around xmldsig ==\n'
sed -n '46,62p' Cargo.toml

printf '\n== references to crypto-common feature names in repository ==\n'
rg -n 'crypto-common.*getrandom|getrandom.*crypto-common|feature.*getrandom|SysRng' .

Repository: structured-world/xml-sec

Length of output: 805


Enable crypto-common/getrandom for SysRng.
xmldsig enables dep:crypto-common, but src/xmldsig/sign.rs uses crypto_common::getrandom::SysRng. crypto-common gates that module behind its getrandom feature, so xmldsig can fail to compile until the dependency enables it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Cargo.toml` at line 34, The xmldsig dependency on crypto-common is missing
the getrandom feature, which prevents crypto_common::getrandom::SysRng from
compiling in src/xmldsig/sign.rs. Update the crypto-common entry in Cargo.toml
to enable the getrandom feature alongside dep:crypto-common so the SysRng path
is available when xmldsig is built.

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.

feat: compute signing reference digests

1 participant