Thanks Tadahiko,
I read through your paper, and it covers exactly the usability issues we have come across! We were wondering if it is possible to perform the specific hashing external to the server (which could be an HSM as in your paper, or timestamp server, etc). For example, for Dilithium the mu := CRH( tr || M) and for Falcon it would be c <- HashToPoint(r || m, q, n). Your paper answers that question, it can be done for Falcon, but not Dilithium (without changing the signature output). So part of our question is whether using a regular external Hash as we do today for RSA and ECDSA (and what you call a boundary type B) somehow reduces the security and we shouldn’t recommend it. We are interested in this because we are looking at defining composite pairs or triples which combine existing signature algorithms like RSAWithSHA256 and ECDSAWithSHA256 with Falcon or Dilithium. Having to change the operational paradigm for an HSM or something like a timestamping server would result in large amounts of data having to be piped across the internet for signatures (as you point out in your paper).
For our composite signature use case it brings up similar questions. We can support a mode where external hashing is done once, and then individually signed by the components (this makes it much more efficient) both internally and externally for the HSM, timestamping, code signing use-cases. However, in the case of Dilithium there would need to be two signature modes Sig = Dilithium (Message) and the other would be Sig = Dilithium ( HASH (Message)). I don’t think that is necessarily a bad thing as long as it is standardized and secure. Alternatively, we could support independent hashing for each component, but that gets strange if you are doing an external hash for ECDSA, but then need to send the whole data for Dilithium. We would likely have to end up supporting sending the whole data if external hashing compromises security of the PQC composites, but then it is even more inefficient as each component would need to hash independently. You also covers this in section 4.3 your paper:
“We can construct type B cryptographic boundaries by adding one more hash function before the execution of PQC’s signature generation algorithm… This approach would improve the efficiency of lattice based digital signature schemes deployed in HSM. It would have a greater impact on Dilithium, but also be applicable to Falcon and other digital signature schemes. Two modes of PQC algorithms utilizing this approach will be able to exist, namely, a PQC algorithm without an additional hash (i.e. original PQC algorithm) and a PQC algorithm with an additional hash. If there are two modes of a digital signature scheme, then the asymmetric operation for those two modes must not be identical. The reason is that, obtaining a signature from the mode with an additional hash function would help attackers who can attack another mode which is without the additional hash function.”
Phillip,
> That is not a new issue and it is one that we discussed at great length for RSA. The hash of the digest is part of the signature payload to prevent substitution attacks.
I think you are in fact mistaking the problem that we’re trying to solve / trying not to un-solve. Nobody is suggesting hash downgrade or substitution attacks. As you point out, that is already solved by existing protocols.
Taking Falcon as an example, the problem as I understand it is that the first internal step of Falcon is:
Sign(m):
r = rand(320);
c = SHAKE(r || m);
…
output (r, s)
Verify(r, s, m):
c = SHAKE(r || m);
this has the nice property that `r` is generated at signing time by the signer. So should SHAKE develop a collision attack similar to the one we saw for SHA1, then the collision pre-computation as still intractable for the attacker because the attacker cannot not know `r` in advance. (Disclaimer: I am just an engineer trying to wrap my head around this, corrections welcome!).
So the concern with hash-then-sign is that if `m` above is itself a message digest, ie `m = SHA256(M)`, then you have un-done the collision resistance that is built in to the Falcon primitive, essentially reducing the security properties of Falcon. Adding the message digest to the signed content does not help if the attacker is holding two messages with the same SHA256 hash.
My simplified-to-the-point-of-being-wrong understanding is that this would be no worse than what we do with RSA and therefore might be acceptable in some use cases, but it is also ignoring cryptographic improvements beyond RSA.
Disclaimer: this whole email should be viewed as a question that we are seeking confirmation of.
---
Mike Ounsworth
Phillip,
> That is not a new issue and it is one that we discussed at great length for RSA. The hash of the digest is part of the signature payload to prevent substitution attacks.
I think you are in fact mistaking the problem that we’re trying to solve / trying not to un-solve. Nobody is suggesting hash downgrade or substitution attacks. As you point out, that is already solved by existing protocols.
Taking Falcon as an example, the problem as I understand it is that the first internal step of Falcon is:
Sign(m):
r = rand(320);
c = SHAKE(r || m);
…
output (r, s)
Verify(r, s, m):
c = SHAKE(r || m);
this has the nice property that `r` is generated at signing time by the signer. So should SHAKE develop a collision attack similar to the one we saw for SHA1, then the collision pre-computation as still intractable for the attacker because the attacker cannot not know `r` in advance. (Disclaimer: I am just an engineer trying to wrap my head around this, corrections welcome!).
So the concern with hash-then-sign is that if `m` above is itself a message digest, ie `m = SHA256(M)`, then you have un-done the collision resistance that is built in to the Falcon primitive, essentially reducing the security properties of Falcon. Adding the message digest to the signed content does not help if the attacker is holding two messages with the same SHA256 hash.