0
$\begingroup$

I'm updating some piece of software I wrote quite some time ago. It is supposed to sign some content. So at the moment I have the following process:

  1. I have a (private, public) keys pair. These can change in time, but rarely.
  2. Some data is given.
  3. I generate random salt.
  4. I generate message = data + salt + public_key.
  5. I generate hash by calculating hmac_sha512(salt, message).
  6. I sign the hash with a private key and generate signature = sign(private_key, hash). I use ECDSA for that.
  7. I obtain the final result = data + salt + public_key + signature, which is then send to someone.

My real case is more complicated, but these steps catch the essentials. The software I'm working on is an authentication server. The server is responsible for generating and maintaining keys and salts, and then signs a short lived access tokens for users to use with other services.

Now I've been thinking about step 4. Generally I could simply do message = data, I don't have to hash and sign the additional + salt + public_key piece.

At this point I don't remember why step 4 looks like this. There's no documentation of course. XD

So the question is: is there any good reason to include both salt and public_key as a piece of hash? Or maybe doing hmac_sha512(salt, data) in step 5 is completely enough?

I also wonder, would it be better to only use say sha512 in step 5, and use salt only in message, and then leave step 4 as it is? Meaning isn't hmac an overkill?

Finally I wonder whether salt is needed at all. The point of hashing is only to have a short signature of constant length. With salt I get slight randomization which is helpful when for example generating the same access token content twice. But then generating same token twice is unlikely to happen anyway, since it contains data like "created at" and "valid until".

There seem to be some subtle differences between those ideas, which I don't really understand.

$\endgroup$
3
  • $\begingroup$ How does this catch the essentials? How is the trust established? Anybody can create a salt and a key pair, right? $\endgroup$
    – Maarten Bodewes
    Apr 2 at 23:39
  • $\begingroup$ @MaartenBodewes no, only server creates salt and keys. User obtains final result which then can be validated against public key. User obtains all public keys available at given time from other endpoint. This is a server that generates short lived access tokens. $\endgroup$
    – freakish
    Apr 3 at 3:27
  • 4
    $\begingroup$ Salt can be useful if the hash is weak (e.g. collision is feasible on an ideal level), but a secure hash should've been used in the first place. Adding salt with HMAC isn't unusally, it has the merit of differentiating salt from message from an algorithm level. Hashing the public key deters key substitution attack, and binds the context. I can't think of anything else. If there's enough comments for you to aggregate an answer, please do post it below. $\endgroup$
    – DannyNiu
    Apr 3 at 6:54

1 Answer 1

5
$\begingroup$

This answer merely expands on this comment.

is there any good reason to include both salt and public_key as a piece of hash?

Reasons to do this include:

  • It's impossible to reuse an existing signature with another salt (e.g. by altering the salt field of a result of step 7).
  • it's impossible to reuse an existing signature with another public key crafted to allow verification of the signature; in other words, it ensures the signature has the Conservative Exclusive Ownership (CEO) property (which ECDSA has, or not, depending on the latitude there is relative to what a public key defines).

I wonder whether salt is needed at all.

The only point I see in salt generated by the signing party (same entity for 3/4/5/6) is that if the hash used in step 5 was broken the way MD5 and SHA-1 are, an unpredictable salt would prevent that data is chosen to create collisions. Assuming an unbroken hash, salt seems only useful if generated beforehand by the party that verify the signature (contrary to the question's setup): salt generated and checked by the verification party prevents replay of the signature.

Note: in the question, salt is entered twice in a hash: in step 4 and 5. This is redundant. Additionally, since salt is public, I see no reason to use it as an HMAC key. And most signature schemes including ECDSA hash what they sign. I conclude the whole step 5 is pointless. Assuming message of step 4 can be uniquely parsed into data, salt, public_key (e.g. if at least two of these fields are fixed size), and an unbroken hash is used for ECDSA, we could remove step 5 and do signature = sign(private_key, message).

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.