How does a server validate the Certificate Verify message in SSL/TLS?

The handshake part of the TLS 1.3 protocol has three goals:

  • exchange certificates;
  • let the server confirms that the client really have the secret key associated with the provided public certificate, without exchanging the secret key;
  • exchange ephemeral keys.

Part 1 - Trust of certificate

Client sends its certificate with Certificate message.

Server determines if the certificate is from trusted source. It verifies the signature of the client's certificate, then the signature of each intermediate certificate, until it finds a trusted certificate, either from a server-side list of trusted certificates, or from a trusted certificate authority (CA).

Pseudo-code:

  1. Alice (client) sends her public certificate to Bob (server) as well as the certificate chain.
  2. Bob hashes the certificate.
  3. Bob decrypts the certificate using the upper-level certificate in the chain.
  4. Bob compares the two results; if they match, Bob has the proof that the certificate was really signed using the upper-lever certificate.
  5. Bob continues through the chain (steps 2, 3, 4) until it finds a trusted certificate.

Part 2 - Trust of client

The client sends the Certificate Verify message:

struct {
  SignatureScheme algorithm;
  opaque signature<0..2^16-1>;
} CertificateVerify;

The signature scheme tells hash function used and signature algorithm.

The signature is produced by the client and verified by the server. The data actually signed is known by client and server and thus not re-sent (it's spaces, a context string, a zero byte and the previous messages).

Pseudo-code:

  1. Alice (client) generates an asymetric key pair.
  2. A trusted authority signs her public key, producing a public certificate.
  3. Alice hashes the data.
  4. Alice encrypts the hash using her encryption key (her private key).
  5. Bob (server) knows, from a previous message: Alice's public certificate and the certificate chain.
  6. Alice sends to Bob: signature, hash function and signature algorithm.
  7. Bob hashes the data.
  8. Bob decrypts the signature using Alice's public certificate.
  9. Bob compares the two results; if they match, Bob has the proof that the signature is associated with the data and Alice's private key generated the signature.

Now, Alice must keep her key secret, and the data must vary between requests to avoid Eve from replaying the request with same data and same signature.

I hope it helps you to better understand.


References:
http://www.garykessler.net/library/crypto.html#why3
https://tlswg.github.io/tls13-spec/draft-ietf-tls-tls13.html
https://nodejs.org/api/crypto.html#crypto_class_sign
https://www.tutorialspoint.com/cryptography/cryptography_digital_signatures.htm


The server has some roots of trust, which it uses, or depending on the application, it may have a CA's cert, or just that client's cert, pinned.

Anyway, it either goes through its trust store and checks if the client cert is signed by something in its store, or if it's pinned, it will just check against the one CA or cert it is configured to check with.