rsa: pass unhashed data to SignerKey/VerifierKey#178
rsa: pass unhashed data to SignerKey/VerifierKey#178lumag wants to merge 1 commit intoRustCrypto:masterfrom
Conversation
Quoting Tony Arcieri: > Generally working directly with raw digests is an antipattern. It's > much less of a problem with RSA than it is with e.g. ECDSA or Schnorr > though, where it can lead to existential forgeries. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
I'd suggest keeping the existing methods as-is, but renaming them to note they accept a prehashed message digest rather than an unhashed message, e.g. You can then implement traits like https://github.com/RustCrypto/signatures/blob/a440df1/ecdsa/src/sign.rs#L175-L202 |
|
@tarcieri this PR changes only new SignerKey/VerifierKey implementations, the old API remains intact. I can change the existing |
|
Let me back up and leave some line notes. |
| } | ||
|
|
||
| pub fn new_with_hash(key: RsaPrivateKey, hash: Hash) -> Self { | ||
| pub fn new_with_hash(key: RsaPrivateKey, hash: Hash, digest: Box<dyn DynDigest>) -> Self { |
There was a problem hiding this comment.
This seems problematic for a number of reasons.
You now have hash and digest parameters. "Hash" and "digest" are synonyms and in the examples you're passing effectively the same thing, it's just an enum variant versus a Box-ed digest instance. This isn't DRY.
I think you should pick one of hash or digest. With hash, you can pick the concrete Digest to use.
Why are you using Box? It erases the digest type, reducing type safety. If you choose to make everything use digest, I'd suggest introducing a generic parameter. That would be a more invasive change, however.
There was a problem hiding this comment.
I thought for using the generic parameter quite a while, while working on Signer/Verifier support. And in the end I decided against it. I wanted to have just two key types for all RSA signing keys (the PKCS1 v1.5 and PSS ones). In fact making the SigningKey/VerifyingKey accept the message rather than pre-hashed value just begs for that from my point of view. This way the all PKCS1 (and all PSS keys) parsed from the SPKI are type-compatible and can be stored and handled in a uniform way. One has to handle two major cases: PKCS1v1.5 vs PSS.
An alterntive of course would be to parse the SPKI.parameters in the app and to perform all the matching inside the app, handling the keys in the generic way in separate arms.
BTW: as we are talking about it, should I also add the Digest argument to the RSA Signature traits?
BTW2: I generally feel that rsa::Hash is misplaced or misimplemented. It either should go to pkcs1 crate or be reimplemented as a trait, which is implemented for different digest types. Or, maybe even better, I can split the Pkcs1v15 signer into padded and unpadded structs/traits/implementations.
There was a problem hiding this comment.
At the very least, there shouldn't be both hash and digest parameters.
There was a problem hiding this comment.
BTW: as we are talking about it, should I also add the Digest argument to the RSA Signature traits?
Which traits are you referring to?
Are you talking about adding another Box<Digest>?
There was a problem hiding this comment.
@tarcieri nah, about adding pss::Signature<D: Digest> to supplement pss::SignerKey<D: Digest>.
There was a problem hiding this comment.
Oh, you're talking about the signature struct?
That's something I've considered but have not done yet with the ecdsa crate. The problem with parameterizing by a D: Digest (as opposed to an enum like Hash) is it complicates interoperability with things like hardware accelerators which may provide their own implementations of specific algorithms.
It's a tricky problem. Perhaps a trait could be used to associate a Hash constant with a particular Digest implementation.
There was a problem hiding this comment.
On a quick note: I'm working on refactoring some JWT-related stuff in my code, and found that having the hash as a generic parameter helps, especially with allowing to impl<D: Digest> From<rsa::RsaPublicKey> for rsa::pss::VerifyingKey<D>, etc.
I ended up building a wrapper in the meantime: https://github.com/matrix-org/matrix-authentication-service/blob/b6e92fb8f7ef81a61dcdee28d12e710743c88860/crates/jose/src/jwa/rsa.rs
Quoting Tony Arcieri:
Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org