Search code examples
encryptionopensslcertificatetls1.3

How and When the Handshake Protocol to use to the Certificate private key?


How does the server using the Certificate Private Key to create Certificate Verify message in TLS 1.3? And how the Client using the Certificate public key to verify the handshake not to be modify? Just in TLS 1.3 not TLS 1.2


Solution

  • As a good overview of the phases of the TLS 1.3 handshake I like to use this site, which breaks down the connection to easier to understand phases then going through the RFC's.

    From the above site:

    Signature

    Because the server is generating ephemeral keys for each session (optional in TLS 1.2, mandatory in TLS 1.3) the session is not inherently tied to the certificate as it was in previous versions of TLS, when the certificate's public/private key were used for key exchange.

    To prove that the server owns the server certificate (giving the certificate validity in this TLS session), it signs a hash of the handshake messages using the certificate's private key. The signature can be proven valid by the client by using the certificate's public key. 08 04 - reserved value for RSA-PSS-RSAE-SHA256 signature 01 00 - 0x100 (256) bytes of signature data follows 17 fe b5 ... 36 9f 9e - a signature over this handshake's hash We can verify the signature ourselves using the server's certificate at the command line:

    build the data that was signed:

    1. add 64 space characters

    $ echo -n '                                ' > /tmp/tosign 
    $ echo -n '                                ' >> /tmp/tosign
    

    2. add this fixed string

    $ echo -n 'TLS 1.3, server CertificateVerify' >> /tmp/tosign
    

    3. add a single null character

    $ echo -en '\0' >> /tmp/tosign
    

    4. add hash of handshake to this point

    $ handshake_hash=3e66361ada42c7cb97f9a62b00cae1d8b584174c745f9a338cf9f7cdd51d15f8 
    $ echo $handshake_hash | xxd -r -p >> /tmp/tosign
    

    copy the signature that we want to verify

    $ echo "17 fe b5 33 ca 6d 00 7d 00 58 25 79 68 42 4b bc 3a a6 90
      9e 9d 49 55 75 76 a5 20 e0 4a 5e f0 5f 0e 86 d2 4f f4 3f 8e b8 61
      ee f5 95 22 8d 70 32 aa 36 0f 71 4e 66 74 13 92 6e f4 f8 b5 80 3b
      69 e3 55 19 e3 b2 3f 43 73 df ac 67 87 06 6d cb 47 56 b5 45 60 e0
      88 6e 9b 96 2c 4a d2 8d ab 26 ba d1 ab c2 59 16 b0 9a f2 86 53 7f
      68 4f 80 8a ef ee 73 04 6c b7 df 0a 84 fb b5 96 7a ca 13 1f 4b 1c
      f3 89 79 94 03 a3 0c 02 d2 9c bd ad b7 25 12 db 9c ec 2e 5e 1d 00
      e5 0c af cf 6f 21 09 1e bc 4f 25 3c 5e ab 01 a6 79 ba ea be ed b9
      c9 61 8f 66 00 6b 82 44 d6 62 2a aa 56 88 7c cf c6 6a 0f 38 51 df
      a1 3a 78 cf f7 99 1e 03 cb 2c 3a 0e d8 7d 73 67 36 2e b7 80 5b 00
      b2 52 4f f2 98 a4 da 48 7c ac de af 8a 23 36 c5 63 1b 3e fa 93 5b
      b4 11 e7 53 ca 13 b0 15 fe c7 e4 a7 30 f1 36 9f 9e" | xxd -r -p > /tmp/sig
    

    extract the public key from the certificate

    $ openssl x509 -pubkey -noout -in server.crt > server.pub
    

    verify the signature

    $ cat /tmp/tosign | openssl dgst -verify server.pub -sha256 \
         -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -signature /tmp/sig
    
     Verified OK