Skip to content

SSL TLS Certificate Pinning

toto edited this page Feb 14, 2013 · 2 revisions

The NXOAuth2Client library supports certificate pinning for TLS/SSL secured connections. This can be useful if you want to protect against certain Man-in-the-middle attacks.

To make use of this you have to tell the account store to only trust specific certificates.

[[NXOAuth2AccountStore sharedStore] setTrustModeHandlerForAccountType:@"myAccountType" 
                                                                block:^NXOAuth2TrustMode(NXOAuth2Connection connection,NSString hostname)
{
      return NXOAuth2TrustModeSpecificCertificate;
}];

More details are explained in NXOauth2Constants.h:81.

Baiscally it boils down to:

  • NXOAuth2TrustModeSystem trusts any certificate chain that iOS/OS X trusts (i.e. no security warning when opening the site in Safari). The default if you do not do anything, just like NSURLConnection.
  • NXOAuth2TrustModeAnyCertificate trusts any certificate presented by the server and does not do any trust checking. This is useful for debugging (e.g. using Charles and should absolutely not be used in production code, as it will make you connections untrustworthy and make using SSL quite pointless.
  • NXOAuth2TrustModeSpecificCertificate trusts only certificates you provide beforehand and therefor implements certificate pinning.

If you want to use pinning, you need to return an array NSData objects containing the bytes of the trusted certificates for the particular hostname like this (provided you have api-cert-in-der-format.pem in your app's main bundle):

[[NXOAuth2AccountStore sharedStore] setTrustedCertificatesHandlerForAccountType:@"myAccountType" block:^NSArray*(NSString *hostname){
    return @[ [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"api-cert-in-der-format" ofType:@"der"]] ];
}

This is of course the most naive implementation possible. In production you not blindly return the contents of the file. To be sure to check that it was not tampered with by checking a cryptographic fingerprint, etc.).

Note that the data returned needs to be in DER format, not PEM. To convert a certificate in PEM format to DER you can use this command line: openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER

To get the PEM formatted certificate copy the --- BEGIN … END CERTIFICATE --- block out of the result of this call (replacing nxtbgthng.com with your TLS host of course): echo "HEAD / HTTP/1.0\n Host: nxtbgthng.com:443\n\n EOT\n" | openssl s_client -prexit -connect nxtbgthng.com:443

Clone this wiki locally