Uh oh!
There was an error while loading. Please reload this page.
signature: add MultipartSigner and MultipartVerifier - #1880
Conversation
newpavlov
commented
Jun 1, 2025
If we are to support such messages, we probably should do it in separate methods or maybe even in a separate trait. |
daxpedda
commented
Jun 1, 2025
I will go ahead and move it into a separate method then. I don't think a separate trait is necessary as the |
signature: use &[&[u8]] for messagessignature: use Iterator<Item = AsRef<[u8]> for messagesI went ahead and added a Will update the other PRs today and see how it looks before moving this out of draft again. |
signature: use Iterator<Item = AsRef<[u8]> for messagessignature: use Iterator<Item: AsRef<[u8]> for messagestarcieri
commented
Jun 1, 2025
This adds a lot of code surface but really doesn’t add any new functionality. We already support IUF signing via Where I guess this could maybe help are for constructions that don’t fit into a strictly IUF API like streaming Ed25519 (non-Ed25519ph) or ML-DSA with external mu. But it’s unclear to me we can build traits which actually abstract over such APIs. If we could, I guess this would be close, but that should probably be the design rationale. |
tarcieri
commented
Jun 1, 2025
Also note that the original proposed |
tarcieri
commented
Jun 1, 2025
FWIW, here's discussion on this sort of API for Ed25519. It was actually removed from this PR, but prior to that, it was suggested to use |
daxpedda
commented
Jun 1, 2025
The intention is not a streaming interface, but a streaming interface would address the problem here indeed as well.
Ah right ... I forgot why I had planned it with So if the approach with Just to clarify: the intention here is to support non-contiguous byte slices for Ed25519/448, ML-DSA and SLH-DSA. |
I agree with the earlier comments that this should be a new trait, like I think it would probably also be good to get everything prototyped in PRs to those crates first before we merge, so we know it's actually a good abstraction. |
daxpedda
commented
Jun 1, 2025
I added support for ML-DSA and SLH-DSA in RustCrypto/signatures#981. I'm happy to make a PR to the Just my 2¢: if you take a look at RustCrypto/signatures#981, the changes are pretty minimal. I really don't believe that going from |
@daxpedda if you look at dalek-cryptography/curve25519-dalek#735, the same cannot be said of Ed25519. I don't want to force signature implementations to have to implement this interface as their only possible choice. We can't even guarantee this interface is possible for all signature algorithms (at least in an unbuffered, |
signature: use Iterator<Item: AsRef<[u8]> for messagessignature: use &[&[u8]] for messagestarcieri
commented
Jun 1, 2025
Alright, that was easier than expected, so let me say this:
I still think it should be a separate trait to keep it out of the way. |
daxpedda
commented
Jun 1, 2025
Sounds good, on it! |
daxpedda
commented
Jun 1, 2025
Let me know what you think. We may want to implement traits on demand, for OPAQUE I will only need |
daxpedda
commented
Jun 1, 2025
Should I add a |
daxpedda
commented
Jun 1, 2025
I went ahead and did both: removed |
daxpedda
commented
Jun 1, 2025
Implementation for ML-DSA and SLH-DSA done in RustCrypto/signatures#982. I hope that dalek-cryptography/curve25519-dalek#763 was sufficient, so I will wait until we are ready to upgrade RustCrypto dependencies there before I make a PR. Probably dalek-cryptography/curve25519-dalek#735 will be relevant as well, as that could be used to implement the Let me know if there is something else you want me to implement/explore/discuss. |
Uh oh!
There was an error while loading. Please reload this page.
signature: use &[&[u8]] for messagessignature: add MultiPartSigner and MultiPartVerifiertarcieri
commented
Jun 1, 2025
@daxpedda regarding |
daxpedda
commented
Jun 1, 2025
FYI: the blanket implementation didn't work because I can't bind Will go ahead and make the PR in |
tarcieri
commented
Jun 1, 2025
Yeah, just go ahead and hand write impls for now |
signature: add MultiPartSigner and MultiPartVerifiersignature: add MultipartSigner and MultipartVerifierDone: RustCrypto/signatures#982. Let me know if you want me to implement it for any other specific crate or for the complete rest. |
daxpedda
commented
Jun 2, 2025
I went ahead and implemented it for the remaining crates. |
tarcieri
left a comment
There was a problem hiding this comment.
Can tentatively approve this, but it would be good to see it integrated into ed25519-dalek as well before a final release. It doesn't look like it will be a problem.
daxpedda
commented
Jun 2, 2025
Implementation of `MultipartSigner` and `MultipartVerifier` added in RustCrypto/traits#1880.
vdods
commented
Sep 11, 2025
I appreciate the work done here, as well as generally for the I'm curious why an implementation that accepted |
daxpedda
commented
Sep 11, 2025
This PR specifically implements a non-streaming API, but doesn't preclude one either. I would also definitely be interested in a streaming interface, but it would probably need some design work on how exactly we are going to take that input. As you mentioned, See |
tarcieri
commented
Sep 11, 2025
@vdods yes, what @daxpedda said. Many signature algorithms implement either That said, not all signature algorithms support such an API, notably neither EdDSA or ML-DSA work with such an API. EdDSA needs two passes over the input message as @daxpedda mentioned, and ML-DSA uses an "external mu" approach where the algorithm controls the digest prefix, both aimed at hardening against collision attacks against the underlying hash function. I think a slight tweak to the design of |
vdods
commented
Sep 11, 2025
Ahh, I think I missed that in EdDSA, the first hash gets fed into the second hash before the message does, and therefore intrinsically doesn't support streaming. If I understand it correctly, the message-signing and digest-signing versions of EdDSA are intrinsically different and the digest version can't be used to produce the equivalent of signing an arbitrary message. But if one were able to choose which algorithm to use, then the digest-signing version would indeed be a good choice to keep the digest process in a fixed buffer of memory and avoid allocations. Here's a dumb and simple (but not elegant) idea about how to support streaming without the need for a "clonable" iterator: Have the caller simply provide two streams/iterators (however that's implemented) that they guarantee to be identical. One stream gets fed into each of the two hashes used in EdDSA. There could even be a debug mode check that uses a "tee" writer to feed each stream en route into a hasher, and then the hash values checked for equality (verifying with negligible error that the streams were indeed identical). Anyway, I get the difficulty now, and am less sure that it would be a good idea. |
tarcieri
commented
Sep 11, 2025
Now that I think about it, the Though, having some way of |
vdods
commented
Sep 11, 2025
Nice, that approach seems good. |
Implementation of `MultipartSigner` and `MultipartVerifier` added in RustCrypto/traits#1880.
## Added - `RandomizedSignerMut` trait (#1448) - `core::error::Error` support (#1711) - Async traits incorporated from the `async-signature` crate (#1720, #2288) - `MultipartSigner` and `MultipartVerifier` traits (#1880) ## Changed - Edition changed to 2024 and MSRV bumped to 1.85 (#1759) - Use `Fn(&mut D)` for `*DigestSigner`/`*DigestVerifier` (#2004) - Bump `rand_core` to v0.10 (#2250) - Bump `digest` to v0.11 (#2300) ## Removed - Error source from display message (#1689) - `std` feature (#1829) - `derive` feature (#1843) - `SignerMut` blanket implementation for `Signer` (#1915) - `PrehashSignature` trait (#1924)
This PR adds new traits for multipart messages:
MultipartSigner,RandomizedMultipartSigner,RandomizedMultipartSignerMutandMultipartVerifier.The idea here is to allow non-contiguous bytes to be passed, which is necessary when the message has to be constructed from multiple sources without wanting to allocate memory for a contiguous message. E.g. for
no_stdenvironments or when the message is rather big but pre-hashing is not applicable, e.g. PureEdDSA, ML-DSA or SLH-DSA.I know this is a rather big breaking change, so let me know what you think!
These new traits can be implemented by a bunch of crates:
ecdsa: ImplementMultipartSigner/Verifiersignatures#982ml-dsa: ImplementMultipartSigner/Verifiersignatures#982slh-dsa: ImplementMultipartSigner/Verifiersignatures#982bign256: ImplementMultipartSigner/Verifierelliptic-curves#1221sm2: ImplementMultipartSigner/Verifierelliptic-curves#1221k256: ImplementMultipartSigner/Verifierelliptic-curves#1221dsa: ImplementMultipartSigner/Verifiersignatures#982lms: ImplementMultipartSigner/Verifiersignatures#982rsa: ImplementMultipartSign/VerifyRSA#525ed25519-dalek: ed25519: implementMultipartSigner/Verifierdalek-cryptography/curve25519-dalek#764ResolvesRustCrypto/signatures#959.