2

So I want to do the following

  1. Check the RSA public key of a https server
  2. Make a GET request to that server
  3. Get a response+signature from the server
  4. I should be able to check if ANY reponse+signature pair matches the publickey.

I was able to get the public key based on another qeustion https://security.stackexchange.com/a/16091

openssl s_client -connect the.host.name:443 | openssl x509 -pubkey -noout

But I don't know how to get a signature on the response message. Is it possible? Do I need to specify a request header with curl? Am I missing something?

The reason I need this is because I'm trying to setup a smart contract (blockchain), with the public key stored. People will send messages and I want to be able to check the messages come from server.

1
  • 1
    With HTTPS, the server does not sign the response. This is a common misnomer. The server signs the keys exchanged during the key-exchange process, but does not sign the response. See crypto.stackexchange.com/questions/5455/… for more info.
    – mti2935
    Jan 29, 2021 at 1:11

2 Answers 2

1

So I want to do the following

  1. Check the RSA public key of a https server
  2. Make a GET request to that server
  3. Get a response+signature from the server
  4. I should be able to check if ANY reponse+signature pair matches the publickey.

There are a number of problems with what you are proposing, as I see it.

First, the RSA private key is not used to sign application data. The TLS handshake sets up a shared symmetric encryption key to protect the data. Furthermore, the integrity of this data is not protected by signing it, it is protected with a MAC that is performed on the application data prior to encryption (MAC-then-encrypt).

Second, The GET request is an application-level HTTP request ("application layer" in the TCP/IP networking model). Similarly, the response (at that same level) is a HTTP response. Neither the request nor the response are encrypted at the application level. The encryption happens via TLS which is "in-between" the application and transport layers. But, like I mentioned above, these individual application data blobs aren't signed by the RSA private key.

If you want to dig in a little deeper, use Wireshark to observe a connection to an HTTPS website. You will see a TLS "Client Hello" as part of the connection setup (this is part of the handshake that sets up the symmetric encrypiton channel). Then you will see a bunch of TLS protocol "application data" blobs. Prior to decryption it will not be clear which correspond to a given HTTP request or response.

1

You appear to want non-repudiation. You cannot get it.

TLS does not provide non-repudiation.

Yes, TLS has all the ingredients to be able to provide non-repudiation, but it does not. TLS chose to be this way on purpose, not by accident, and this is unlikely to change.

TLS provides the ability for the client to know that the response they got came from the server and has not been modified by anyone in between (and also that anyone in between could not have decrypted the traffic without being given the session keys by the client or by the server [1]).

But a transcript of the traffic does not prove anything beyond "a TLS client has connected to the TLS server and started a connection using this cipher suite, at some point in time in the past". All the HTTP requests and responses could have been faked by anyone who had the session keys. For example, I can start a TLS connection with any server, finish the handshake, and then close it, without sending any application traffic. Alternatively, I can send and receive any application traffic and then later discard those packets from the capture. Then I can take the session keys that I know and use them to encrypt and MAC whatever data I want, and there is no way to prove whether the traffic I say I received from the server really came from the server or not.

See previous answers to this question, e.g. https://security.stackexchange.com/a/231019/70830

If we misunderstood you and you merely want to know at the time you receive the response that it came from the server (because you yourself are not faking it), then just follow the TLS spec. Verify the signature in ServerKeyExchange that the server performed using the private key of the end-entity certificate (which the client doesn't have) by using the public key of the end-entity certificate (which the client has, it was sent in the certificate from the server). Construct a certificate chain from the end-entity certificate to a root the client trusts. Verify all the signatures in the chain. Verify the end-entity certificate is not expired and covers the domain in question. Verify using OCSP or CRL that the certificates are not revoked. Perform the ECDH to generate the shared secret. Use the shared secret to generate the AESGCM keys. Verify the GCM MAC.

I use ECDHE and AESGCM in my example because those are the most common cipher suite choices today.

1 - The deprecated RSA key exchange allows decryption by having the private key of the end-entity certificate, but these cipher suites are not present in TLS 1.3 and should not be used in TLS 1.2 in 2021.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .