9

I am currently developing a component for an application that does TCP communication with a device inside a local area network. I use TLS to provide data encryption, integration and authorisation. However, I have to use self signed certificates which will not expire in like 5 years or more.

Since using self-signed certificates exposes my application to man-in-the-middle-attacks, I was thinking about hardcoding the fingerprint of the certificate into my application. When the device sends my it's certificate, I will compare it's fingerprint of the certificate wito to the hardcoded fingerprint.

Now, does this improve the security of my application? Is it possible for an attacker to produce his own self-signed certificate that has the same fingerprint? I also plan on using a client-certificate which I will send to the device during TLS-handshake. The device than has to check the fingerprint of my certificate.

Is this solution valid?

Thanks in advance for your answers!

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
WMEZ
  • 341
  • 2
  • 11
  • I don't undestand - if it was over the internet, the request goes from router to router and one of them can tamper the data and send you fake certificate, but in LAN man-in-the-middle could only spy the traffic (AFAIK), so how self-signed certificates exposes your application to man-in-the-middle-attacks in LAN? – BornToCode May 04 '15 at 13:32

3 Answers3

10

In SSL/TLS, the client uses the server's public key. Since in general the client does not know the server's public key in advanced, it expects to obtain it through the magic of the Public Key Infrastructure: the server's public key will be presented in a certificate and the client will be able to verify that:

  • the certificate contents are genuine (that's validation: signatures and names and certificate extensions are correct and link up to a trusted root);
  • the certificate is owned by the intended server (the expected server name appears in the Subject Alt Name extension of the certificate, or its Common Name if there is no SAN extension).

Now all of this is needless complication if the client already knows the public key; if that key is known a priori, then the client can just use it and simply ignore the certificate sent by the server.

For the sake of compatibility with the formal specification of the protocol, and to more easily reuse existing libraries and implementation, it is probably even simpler to do what you suggest, i.e. verify that the server's certificate is bit-to-bit the expected certificate, and let the code extract the public key from that. The "fingerprint", if it is computed with a hash function which is resistant to second preimages (e.g. SHA-1), can be used for that check. This is fine.


In your case, I understand that the server is the device, and the client is your application. Your application won't be fooled (talking to a fake device) only as long as the attacker has not compromised the device's private key, i.e. extracted it from a device. If you have several devices then each device should have its own private/public key pair. If all devices have the same key pair, then the private key cannot be considered "private": a secret which is known to more than two or three people is not a secret, but a rumour.

The "safe" way is then to have some sort of initialization phase, under controlled conditions, where the application instance learns the fingerprints of the devices to which it will thereafter connect (maybe the application generates the public/private key pairs and self-signed certificates, and imports them into the devices).

This is the security model used in SSH: the first connection from a client to a given server requires an explicit confirmation (the client shows the server's public key fingerprint, and the human user is supposed to verify it by, for instance, phoning the server sysadmin); afterwards, the client trusts that public key because it remembers the fingerprint.


The "remember the key" model works well, but you must be aware that it forfeits the PKI feature known as revocation: an out-of-band, automatic mechanism to convey damage containment information. If the private key of one of the devices is compromised, then the thief can thereafter run a fake device and fool your application into connecting to it; to avoid this situation to persist, the application must somehow be warned that a given certificate fingerprint must no longer be accepted. Revocation checks, with regularly published CRL or OCSP responses, is an automatic method to do that. When you have remembered fingerprints, there is no PKI, thus no CRL. But the need may be still there.

If you follow the no-PKI road, with embedded certificate fingerprints, then you have to decide whether you need something to ensure the job normally done by CRL.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • 1
    Thank you for your detailed answer. I figured that each devices will create a keypair and certificate on the very first boot process. Maybe a new certificate is created in the future (in case the key gets somehow compromised). I decided to do it in the SSH way that you explained. If I receive a certificate that is self-signed and whose fingerprint is unknown, the user has to explicitly confirm that he wants to connect. If he does, then the fingerprint is stored and no confirmation is needed in the future. If a key gets compromised, I remove the fingerprint from the storage. Does that sound ok? – WMEZ Feb 05 '14 at 09:48
4

What you are doing here sounds somewhat similar to certificate pinning. In some situations this can actually provide better security than using a CA issued certificate (in that you don't have to trust the CA)

The downside is that it makes certificate management (e.g. revocation, re-issuing) a manual process which may be a real problem, depending on your use case.

Rory McCune
  • 60,923
  • 14
  • 136
  • 217
  • The thing is that revocation or re-issuing certificates will be complicated no matter what. The certificates are stored on the devices which are set up in different LANs on differenct places (maybe even different countries) with no internet connection. In order to replace or re-issue the certificate, a technican would have to connect to the LAN, set up a SSH connection and replace the certificate. I am talking about technical devices which are not available to the public. However, some devices may be used on a daily basis while other's are used once every 2-3 years. – WMEZ Feb 04 '14 at 08:26
  • yep that's the advantage of a CA issued cert that problem is reduced (as long as you trust the CA). If however self-signed certs are a requirement, then pinning would seem to be the way to go. – Rory McCune Feb 04 '14 at 08:56
2

Yes, this is effectively the same as trusting your root certificate used to self-sign the certificate. The verification process for a certificate is to take the thumbprint and verify that the signature you have from a trusted CA matches the thumbprint. Verifying the thumbprint directly is an equivalent action.

AJ Henderson
  • 41,816
  • 5
  • 63
  • 110