So What Is A PreHash, And What Has it to do With Post Quantum Signatures?
The cybersecurity world is changing, and where the signature methods of RSA, ECDSA and EdDSA are likely to be replaced by FIPS 204 (aka ML-DSA Module-Lattice-Based Digital Signature Standard— Dilithium) and FIPS 205 (aka SLH-DSA (Stateless Hash-based Digital Signature Standard — SPHINCS+).[here]:
As part of the standard, we define the key generation process, the signing processing, the verification process and also Pre-hashing [here]:
So what is a Pre-hash?
Pre-hashing
In the ML-DSA method, we can create a pre-hash of a message and then use this to create a digital signature. Normally, in a digital signature, Bob will take a message (M) and then pass this and his private key (sk) to a signature method for:
Sig=Sign(sk,M)
and where we pass the message to the signature method, and which will then take a hash of the message and produce the signature:
But, what if the message is large and we are using a limited processing device? Well, for this, we could perform the hashing outside the signature method, and thus perform a pre-hashing process, and pass the pre-hash into the signature method:
Sig=Sign(sk,H(M))
and where the message value passed will be much smaller than a large method. This will help with the buffering requirement for the signature method, and where we typically will just require 32 bytes (for a 256-bit hash) or 64 bytes (for a 512-bit hash):
These days a typical hash is produced by SHAKE256, and where we output a 512-bit hash value:
With SHAKE256, we have an XOF function; where we can create any length of hash. Normally, for a Pre-hash, this is a 512-bit hash.
Pre-hashing reduces the burden on the signer
The great advantage of a Pre-hash is that we can use a powerful CPU to generate the Pre-hash and then pass it to a limited processing device, such as a smart card. It is unlikely that the smart card will have a great deal of memory to buffer a large message. In this case, the smart card has a private key stored, and then where a powerful CPU computes a Pre-hash and then passes this to the smart card, and which then returns the signature based on the Pre-hash, the signing method and the private key:
Supporting other cryptographic hashing methods in signature
Another advantage of using a pre-hash is that we might want to use a new cryptographic function that is not supported by the signature method. For example, we might want to use Blake2b for our signature. For this, we can then create a Blake2b Pre-hash:
Overcoming forgery attacks
One problem is that we need to make sure that the verification process knows about the pre-hash and where a pre-hash needs to be created before the verification process. This can lead to a forgery attack. Luckily this can be overcome by using domain separation. With this, we add a context (ctx), and where the Pre-hash is computed with:
H = hash(M) using SHAKE256 with 512-bit output
S = sign( 0 || OID(SHAKE256 with 512-bit output) || ctx || H )
In this case we identify the SHAKE256 with a 512-bit output with its OID in the message password to the signature production. The normal signature would then just be:
S = sign(1 || ctx || M )
The method of using the OID and Pre-hash is defined in the ML-DSA specification [here]: