Skip to content

Sign/verify by digest update + StreamVerifier #735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jun 2, 2025

Conversation

robjtede
Copy link
Contributor

@robjtede robjtede commented Mar 8, 2025

see description and discussion in #556

this PR reuses all commits from that one, and adds in the feature guard we talked about

nightly CI failure is unrelated

mkj and others added 6 commits May 9, 2025 04:13
This struct can be use to implement verifiers with incremental updates
These allow signing/verifying a non-prehashed message
but don't require the whole message to be provided at once.
This allows it to use the same implementation as non-stream signature
verification.
@tarcieri tarcieri mentioned this pull request May 31, 2025
Copy link
Contributor

@tarcieri tarcieri left a comment

Choose a reason for hiding this comment

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

I'll give a tentative utACK with questions about if this has impact on benchmarks.

The main notable thing about this PR IMO is it refactors the recompute_R function into a stateful/IUF-ish RCompute struct. That seems fine to me.

I'll also argue the core rationale for this PR is similar to the "external mu" approach of ML-DSA in that rather than making a mutant IUF variant of an algorithm (i.e. Ed25519ph) you instead expose an API which allows IUF-like operations on standard Ed25519 signatures. Though "external mu" is perhaps a lot more elegant than this, but I digress.

Co-authored-by: Tony Arcieri <[email protected]>
Copy link
Contributor

@rozbb rozbb left a comment

Choose a reason for hiding this comment

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

Thank you! Left some notes on ways we can simplify this. I've always got an eye towards long-term maintainability, so I really lean towards having less than more. Let me know if I cut too deep :)

/// Do NOT use this function unless you absolutely must. Using the wrong values in
/// `ExpandedSecretKey` can leak your signing key. See
/// [here](https://github.com/MystenLabs/ed25519-unsafe-libs) for more details on this attack.
pub fn raw_sign_byupdate<CtxDigest, F>(
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you sure it makes sense to have this function? The (prefixed) hash of M needs to be computed twice for signing. This restricts the kinds of things the msg_update closure can do. Eg it cannot consume an incoming network stream, since it'll have nothing to hash the second time it's called.

So I propose: don't make new signing procedures, and leave the current signing procedures alone. Either that, or, if we really want, we can make it take msgs: &[&[u8]] to handle non-continguous messages (as suggested below). What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

happy to remove this one too as my main interest is the new StreamVerifier which works fine without these new functions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed in 9a8fd74

Copy link
Contributor

Choose a reason for hiding this comment

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

Ty! Can you also remove the second line of the changelog entry and raw_sign_byupdate?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, should have been clearer. All of the raw_sign_byupdate methods. Including this one, and revert raw_sign to the original

Copy link
Contributor

@mkj mkj Jun 1, 2025

Choose a reason for hiding this comment

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

The rationale is in #556 (comment)

The signature is over a message made up of various parts, I'm using the serialiser to feed directly into the hash function. This is an example of using it, instead I've had to allocate a few hundred byte buffer to write into then sign (and it has fixed username length limitation assumptions). A &[&[u8]] wouldn't work for my case.

https://github.com/mkj/sunset/blob/3c7d6879da93684832f8ec19df4191523999a2f3/src/sign.rs#L324-L338

Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh ok I’m open to this. I feel bad for requesting so many changes. I can break this into a separate PR today

@rozbb
Copy link
Contributor

rozbb commented Jun 1, 2025

@tarcieri re performance: I see no statistically significan't changes on my M1 Air, EXCEPT I get an 11% slowdown on strict signature verification. Regular signature verification is unaffected though. I'm baffled at that

@tarcieri
Copy link
Contributor

tarcieri commented Jun 2, 2025

See also: #763

@rozbb
Copy link
Contributor

rozbb commented Jun 2, 2025

Ok I tested on an M3 MBP and can't observe a performance difference at all. I'm willing to believe that the regression is spurious.

@rozbb rozbb merged commit 6dc7a1c into dalek-cryptography:main Jun 2, 2025
14 checks passed
@robjtede robjtede deleted the parts3 branch June 2, 2025 23:04
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.

4 participants