How to compare SSL certificates using AFNetworking
Solution 1
The term you're looking for is SSL Pinning, where the app verifies that a known certificate or public key matches one presented by a remote server.
AFNetworking supports both pinning with certificates or public keys. You'll need to add the certificate(s) or public key(s) to your app's Bundle, and enable the feature by setting either the defaultSSLPinningMode
property on AFHttpClient or the SSLPinningMode
property on AFURLConnectionOperation
.
You can pin using AFSSLPinningModePublicKey
or AFSSLPinningModeCertificate
. AFSSLPinningModeCertificate
means that the server's certificate must exactly match one of those in the bundle.
AFSSLPinningModePublicKey
is more liberal and means that the server's certificate must match for any public key in the bundle, or any public key attached to certificates in the bundle.
There's an example of setting the pinning mode in the AppDotNet example.
Solution 2
To expand a bit on David's answer with respect to AFSSLPinningModePublicKey
versus AFSSLPinningModeCertificate
. Ideally, you would pin the public key and not the certificate. That's because some sites and services, like Google, rotate their certificates every 30 days or so. But they re-certify the same public key.
The certificates are rotated frequently to keep the size of the CRL small for mobile clients. But they re-certify the same public key (rather than creating a new one) to allow for key continuity testing.
Public key pinning is why tools like Certificate Patrol miss the mark. The certificate is expected to change; the public key is not.
Public key pinning is a lot like SSH's StrictHostKeyChecking
, if you are familiar with it.
OWASP has a write-up on it too at Certificate and Public Key Pinning.
BigLex
Updated on July 22, 2022Comments
-
BigLex almost 2 years
In my iPhone app I'm using an
https
connection with a self-signedSSL
certificate to download sensible data (username and password) from a server.This app is for private use only, it is not meant for production.
I'm using
AFNetworking
to manage thehttps
connection but, since my certificate isn't signed from a CA, in order to make it work I had to add the following to the header of theAFURLConnectionOperation
class:#define _AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_ 1
But with this my app will allow any certificate.
Is there a way to allow only the certificate from my server maybe bundling it in the app and comparing it with the certificate provided by the server in the https connection? And if it were possible, would there be any significant advantage in terms of security?
I'm very new to security and I'm kind of confused.
-
BigLex almost 11 yearsthank you for pointing me in the right direction. Are there any significant security advantages doing this?
-
David Snabel-Caunt almost 11 yearsSSL Pinning offers additional protection from MITM attacks and compromised CAs. There's some insight here.
-
BigLex almost 11 yearsJust what I was looking for! One last question, do I need to somehow set the certificate file against which the AFNetworking Library should compare the certificate provided by the server or the library will find it on its own?
-
David Snabel-Caunt almost 11 yearsAFNetworking will automatically find certificates in the bundle root.
-
BigLex almost 11 yearsMy certificate has .crt extension not .cer and when I try to connect the following error is logged in xcode:
Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x7157d40
the header file says that the certificate should be .cer may this be the problem? -
David Snabel-Caunt almost 11 yearsI think you'll need to convert the certificate to the right format but I don't know the best way offhand
-
Gabriel.Massana about 10 yearsconvert
.crt file
to.cer file
: Open terminal and run the following command.openssl x509 -in www.mydomain.com.crt -out www.mydomain.com.cer -outform der