Take the 2-minute tour ×
Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

One of the inputs of RSA-PSS signing and verification is the salt size. According to PKCS#1, you must know the salt size before the verfication is carried out. However, this makes interoperability impossible: if, for example, I want my program to verify a signature generated by OpenSSL, then I can't do the verification since I don't know the size of the salt that was used.

It is possible to deduce the salt size due to its encoding. However, PKCS#1 does not mention if this should be done. (OpenSSL supports this)

My question is: is it safe to deduce the salt size, or the salt size must be an input of the verification algorithm?

share|improve this question
add comment

1 Answer

up vote 5 down vote accepted

Normally, the salt length is part of the signature parameters, i.e. the things which tell you that the signature is indeed of type RSA-PSS, what hash function is used and what mask generation function is used.

Many protocols use ASN.1 to encode such parameters (e.g. CMS, the offspring of PKCS#7 and basis for signed emails with S/MIME). PKCS#1 defines (in annex A) an ASN.1 structure for RSA-PSS (RSASSA-PSS-params). The identification for an algorithm uses the generic:

AlgorithmIdentifier ::= SEQUENCE {
    algorithm     OBJECT IDENTIFIER,
    parameters    ANY DEFINED BY algorithm
}

(I am using old-style ASN.1 notation, which is easier to read for human beings.) In plain words, a structure which contains a symbolic identifier (here 1.2.840.113549.1.1.10, which means "RSA with PSS") and parameters which depend on the algorithm. In the case of RSA-PSS, the parameters shall be:

RSASSA-PSS-params ::= SEQUENCE {
    hashAlgorithm      [0] HashAlgorithm      DEFAULT sha1,
    maskGenAlgorithm   [1] MaskGenAlgorithm   DEFAULT mgf1SHA1,
    saltLength         [2] INTEGER            DEFAULT 20,
    trailerField       [3] TrailerField       DEFAULT trailerFieldBC
}

where hashAlgorithm tells which hash function shall be used to initially process the data (it is actually a nested AlgorithmIdentifier structure), maskGenAlgorithm defines the "mask generation function" used within PSS (it is a kind of hash function with an extensible output length; again, a nested AlgorithmIdentifier structure), saltLength is the salt length, and trailerField is a symbolic value which defines the "trailer byte" added in PSS (usually of value 0xBC, but that could be changed in the future).

There is only one standard MGF, and it is called MGF1, which itself relies on an underlying hash function. So the MaskGenAlgorithm structure (an AlgorithmIdentifier structure under another name) contains an object identifier which says "this is MGF1" (1.2.840.113549.1.1.8) and uses as parameters yet another AlgorithmIdentifier structure (yep, third level of nesting) which designates the hash function to use with MGF1.

Bottom-line: to actually verify an RSA-PSS signature, you have to know the following:

  • that the signature is indeed of type RSA-PSS;
  • the hash function used to first process the hashed data, and produce the right half of the "DB" value in PSS;
  • the MGF used in PSS (normally MGF1, since this is the only defined MGF function, but MGF1 itself needs some parameters, namely the hash function it should rely on);
  • the salt length;
  • the trailer byte (normally 0xBC; that's the only one people ever use and there is little reason to change it).

If you worry about the salt length only, then this means that in whatever protocol you are defining, you already took care of encoding all the other parameters (or hardcoding them in the code), so I suggest that you encode the salt length in the same place.

It is customary (but not mandatory) to use parameters such that the MGF is MGF1, built over the same hash function than the one used to process the signed message, and to set the salt length to be equal to the length of the output of the hash function. In that sense, you could reduce, in practice, the encoding of parameters to a single hash function (PKCS#1 says "SHA-1" but nowadays you would rather use something with a better outlook, such as SHA-256).


On the choice of salt length

The salt is related to the security proof of PSS. The point of PSS, with regards to the older and simpler "v1.5" padding, is that PSS benefits from a mathematical proof which binds its security to the core RSA operation (the modular exponentiation). It is thus shown that in order to break RSA-PSS, you have be able to break the exponentiation part (be able to compute some $e$-th roots modulo $n$), to some extent. The "extent" is what is called the tightness; the tighter the proof the better. It so happens that a salt length equal to the hash output length yields a tighter proof than a salt length of 0 (i.e. no salt at all). Note that we are not talking about actual attacks or even actual defence; the proof does not say that an empty salt is weaker, only that the maths give more guarantees with a non-empty salts. See PKCS#1, page 34, note 4: this contains pointers to the relevant scientific articles.

In practice, nobody knows how to break PSS with empty salts; nobody knows how to break v1.5 signatures either. If you bother using PSS at all, then this must be because of the mathematical proof, since there is no other advantage of PSS over the much simpler v1.5 padding. Thus, you probably want a non-empty salt.

On inferring the salt length

This is your actual question; all of the above is just a preambule. You can infer the salt length from the signature itself, and it is safe, because in actual protocols where the salt length is encoded in the parameters structure, that structure itself is not protected in any way. So an attacker could easily alter the encoded salt length as he sees fit.

But mind the fine details: it is OK to infer the salt length only insofar as the inferred salt length is a length which you would have accepted if it had been offered encoded in an RSASSA-PSS-params structure. If you want to enforce a minimal salt length (because of some slightly maniacal perception of the importance of mathematical proofs), then you have to enforce it also for the salt length you infer.

My advice is still to encode the salt length in what is used as "parameters" in your specific application. It feels "cleaner" and will help you interfacing with existing RSA implementation (which usually expect to be given the salt length as parameter, not to infer it from the signature itself).

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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