I would like to implement TLS1.3 Certificate Verify functionality (without external library, openssl etc.).
I am a bit confused about the documentation. According to it I am believing, that the algorithm, using RSA-PSS-RSAE-SHA256 is the following:
Parsing and checking certificates received in the Certificate handshake is Ok. From here I can also get the public key (RSA n and e) for the Cerificate Verify
According to RFC8446/4.4.3, the content to sign consists of: 64 * 0x20 + "TLS 1.3, server CertificateVerify" + 0x00 + transcript-hash of messages (in our case, sha256 hash of concatenating all handshakes ClientHello...Certificate). I consider content to be message
Min the followings.RSASSA-PPS with EMSA-PSS (for the selected signature algorithm) is described in RFC8017/8.1.2, 9.1.2. There are two main steps: The signature has to be RSA-decrypted (8.1.2); EMSA-PSS verification has to be done (9.1.2):
- The firts one is rather trivial, resulting in Encoded Messaget
EM - hash (
H), andsaltcan be extracted from that one. Details are in the RFC document - Hash of M must be calculated:
mHash = sha256(M) H'can be calculated by sha256 hash of(8 * 0x00 + mHash + salt)
- The firts one is rather trivial, resulting in Encoded Messaget
If
H == H', then verification is successful.
At least this is how I interpret this. But it does not work:
- I am almost sure, that my transcript-hash is good, I use the handshake concatenation in multiple positions in TLS communcation successfully, and calculating the hash of it is also not a big deal
- So I am almost sure, that the content (prefixing the content hash with elements as seen above) is also Ok.
- There might be a gap between RFC8446 and RFC8017, but I did not find any info on that. Maybe
Mof RSASSA-PPS is not the same as the content of TLS Certificate Verify content. - I could evaluate
Handsaltusing the signature and the public key (there are good checking opportunities for this, so this is surely Ok in my case)
But as a result H != H'.
So I probably misunderstand something with this algorithm. Maybe the message M should be something different, or something else is missing. Is there any good description somewhere, which leads through this process step by step? Or a source which can be run part by part, so that I can check where my implementation deviates? (Pyhton or perl is preferred, but any major languages can be good)