You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
You probably know this, but I thought I'd mention it anyway as I haven't found something documenting this:
I noticed that with the pre-hashed (ED) version, a Blake2b hash is directly signed with the regular Ed25519 scheme, without any domain separation, as the scheme used (Ed/ED) is never signed. This means that in case of a pre-hashed signature it is trivial to forge one specific signature: given a pre-hashed signature for file.txt, change the algorithm to Ed, and it will work as a signature for a file containing the Blake2b hash offile.txt. (The other way around is technically also possible, but only if what is signed is already a file containing a (non-encoded) Blake2b hash for which the pre-image is known.)
Example attack
For an attacker, this would probably mostly be useful as a way to disrupt services. For example, say I have a service running that regularly downloads a pre-hashed signed JSON config file, verifies the signature, replaces the previous config file, parses the file, and applies the configuration. Now an attacker might replace the file with its hash, update the algorithm in the signature, and give it to the service. The service will then happily verify the signature, replace the previous config file, and crash while parsing the config because the hash is not valid JSON. Compare this with a more general DoS attack where an attacker just blocks the download: at least there the server can later retry and it does not need to be manually restarted with a valid config file again.
In some (hopefully) niche cases where the original file was a binary file which was basically a struct serialization, the hash may actually be interpreted as valid data, but likely with very extreme values.
Mitigations / solutions
I'm not sure if all this was deliberate to keep the design of the tool simple, but it seems undesirable to me that an attacker would be able to forge any signature.
A mitigation would be to not use the pre-hashed variant, or always check that the variant used is the one you were expecting (ED and not Ed), if that is known beforehand.
As a solution, the latter could be integrated per key, such that a key may only be used to verify one variant, but then it will be hard to switch to another variant if that is desired. Alternatively, the variant could be signed, e.g. in the trusted comment signature, but this will be harder to accomplish keeping backwards compatibility in mind.
Underlying cause
For some context, I would say that the underlying problem is that Minisign does not use the Ed25519ph scheme from RFC 8032, which would set the pre-hash flag to 1 and thus provide separation between the two cases. However, Ed25519ph uses SHA-512 instead of Blake2b. (Of course this is not the only way to accomplish separation, e.g. Ed25519ctx or just signing the variant in Ed25519 would work as well.)
The text was updated successfully, but these errors were encountered:
A format identifier should have been part of the input being signed.
Minisign predates the EdDSA RFC; Ed25519ph didn't exist back then.
A signature can essentially only verify two different representations of the same message. But indeed, parsers can get content they didn't expect.
The best thing to do is probably to always prehash and gradually deprecate non-prehashed files. Minizign has a -H option that will only verify prehashed inputs; this is something that can be easily added to other implementations.
You probably know this, but I thought I'd mention it anyway as I haven't found something documenting this:
I noticed that with the pre-hashed (
ED
) version, a Blake2b hash is directly signed with the regular Ed25519 scheme, without any domain separation, as the scheme used (Ed
/ED
) is never signed. This means that in case of a pre-hashed signature it is trivial to forge one specific signature: given a pre-hashed signature forfile.txt
, change the algorithm to Ed, and it will work as a signature for a file containing the Blake2b hash offile.txt
. (The other way around is technically also possible, but only if what is signed is already a file containing a (non-encoded) Blake2b hash for which the pre-image is known.)Example attack
For an attacker, this would probably mostly be useful as a way to disrupt services. For example, say I have a service running that regularly downloads a pre-hashed signed JSON config file, verifies the signature, replaces the previous config file, parses the file, and applies the configuration. Now an attacker might replace the file with its hash, update the algorithm in the signature, and give it to the service. The service will then happily verify the signature, replace the previous config file, and crash while parsing the config because the hash is not valid JSON. Compare this with a more general DoS attack where an attacker just blocks the download: at least there the server can later retry and it does not need to be manually restarted with a valid config file again.
In some (hopefully) niche cases where the original file was a binary file which was basically a struct serialization, the hash may actually be interpreted as valid data, but likely with very extreme values.
Mitigations / solutions
I'm not sure if all this was deliberate to keep the design of the tool simple, but it seems undesirable to me that an attacker would be able to forge any signature.
A mitigation would be to not use the pre-hashed variant, or always check that the variant used is the one you were expecting (
ED
and notEd
), if that is known beforehand.As a solution, the latter could be integrated per key, such that a key may only be used to verify one variant, but then it will be hard to switch to another variant if that is desired. Alternatively, the variant could be signed, e.g. in the trusted comment signature, but this will be harder to accomplish keeping backwards compatibility in mind.
Underlying cause
For some context, I would say that the underlying problem is that Minisign does not use the Ed25519ph scheme from RFC 8032, which would set the pre-hash flag to
1
and thus provide separation between the two cases. However, Ed25519ph uses SHA-512 instead of Blake2b. (Of course this is not the only way to accomplish separation, e.g. Ed25519ctx or just signing the variant in Ed25519 would work as well.)The text was updated successfully, but these errors were encountered: