Implementing SSL Pinning(Public Key) in React-Native Applications in Native Way

Prishan Maduka
4 min readMar 26, 2020

React-native is a highly demanding mobile application development technology. You can find so many tutorials, articles, publications on the topic of React-native which cover the content from alpha to omega.

When it come to SSL Pinning you can learn about SSL Pinning using the following article.
An Introduction to SSL Pinning

Simply there are 2 ways of implementing SSL Pinning in react-native application.

1) Using react-native libraries react-native-pinch or react-native-ssl-pinning
2) Using native method.

Above mentioned react-native libraries are easy to implement, but there are some limitations. In this article we are going to focus on how to implement in native way.

Since we are using native platforms, there are two different implementations for android and ios. When compared to android, ios implementation is easy.

First of we need to generate the certificate for your domain using following command.
openssl s_client -showcerts -servername <domain(i.e. google.com)> -connect <domain(i.e. google.com)>:443

This will output the entire certificate in the chain with leaf certificate in the top and root certificate in the bottom.

fig 1.0 — Entire certificate

As shown in the diagram you can see there are two keys inside ‘BEGIN CERTIFICATE’ and ‘END CERTIFICATE’ blocks. Copy these two keys into separate files and save them in .pem file format (i.e. leaf-certificate.pem). You should keep in mind that when we are saving these keys we should include ‘BEGIN CERTIFICATE’ and ‘END CERTIFICATE’ delimiters as follows

fig 1.1 — leaf-certificate.pe

Anyway for iOS, we are using TrustKit for the SSL Pinning. In this repository there is an inbuilt script(i.e. get_pin_from_certificate.py) to get the public key sha256 hash from the .pem file. Download this file and use the following command to retrieve the public key hash.

$ python get_pin_from_certificate.py <your .pem file>

This will output your key as follows:

fig 1.2— SHA256 Key

Its better if you generate keys for both leaf and root keys.Now all the certificate configurations are done and we are good to go to our implementations.

IOS Implementation

As I mentioned earlier we need to use TrustKit for ios.

Open the XCode workspace of your project and add the following to your pod file.
pod ‘TrustKit’

Then run :
pod install

(i) Method 1 — For Simple Applications

Now TrustKit has been added to your project. Then we have to update Info.plist file to initialize TrustKit.

<key>TSKConfiguration</key>
<dict>
<key>
TSKPinnedDomains</key>
<dict>
<key>
--- YOUR DOMAIN --- </key>
<dict>
<key>
TSKEnforcePinning</key>
<true/>
<key>
TSKIncludeSubdomains</key>
<true/>
<key>
TSKPublicKeyAlgorithms</key>
<array>
<string>
TSKAlgorithmRsa2048</string>
</array>
<key>
TSKPublicKeyHashes</key>
<array>
<string>
--- SHA256 KEY 01 --- </string>
<string>
--- SHA256 KEY 02 --- </string>
</array>
</dict>
</dict>
</dict>

Add the above lines to your .plist file and replace your domain and SHA256 hash keys generated.

(i) Method 2— For Complex Applications

Add following changes to AppDelegate.m

#import <TrustKit/TrustKit.h>- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{  [self initTrustKit];
return YES;
}- (void)initTrustKit { NSDictionary *trustKitConfig = @{
kTSKSwizzleNetworkDelegates: @YES,
kTSKPinnedDomains : @{
@"DOMAIN NAME" : @{
kTSKEnforcePinning : @YES,
kTSKIncludeSubdomains:@YES,
kTSKPublicKeyHashes : @[
@"--- SHA256 KEY 01 ---",
@"--- SHA256 KEY 02 ---"
],
kTSKPublicKeyAlgorithms : @[kTSKAlgorithmRsa2048],
},
}
};
[TrustKit initSharedInstanceWithConfiguration:trustKitConfig];}

NOW ALL IS WELL AND WE ARE GOOD TO GO !

ANDROID Implementation

As I mentioned earlier, Android implementation is little bit trickier than that of iOS. But it is not much hard. In the above iOS implementation we have already generated the required keys for public key pinning. We are going to use same keys for this as well.

In this we are using Android’s OkHttpClient which supports from react-native version 0.54.

First of all create a Java Class in the android/app/src/main/java/package_name folder and add the following code.

package com.example;

import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.ReactCookieJarContainer;
import okhttp3.CertificatePinner;
import okhttp3.OkHttpClient;
import okhttp3.CertificatePinner.Builder;

public class CertificatePinningClientFactory implements OkHttpClientFactory {

@Override
public
OkHttpClient createNewNetworkModuleClient(){

String hostName = " YOUR DOMAIN ";

String certificatePublicKey1 = "sha256/< ADD KEY 01 >";
String certificatePublicKey2 = "sha256/< ADD KEY 02 >"; OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();

CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostName, certificatePublicKey1)
.add(hostName, certificatePublicKey2)
.build();

clientBuilder.certificatePinner(certificatePinner);
clientBuilder.cookieJar(new ReactCookieJarContainer());
return clientBuilder.build();
}
}

In the above update your domain and keys.

NOTE — Keep in mind that, in android when you are implementing you must prepend keyword ‘sha256/’ to the keys generated

Now the final step. Add the following lines to onCreate() method of MainActivity.java class.

package com.example;.......import com.facebook.react.modules.network.OkHttpClientProvider;
import com.example.CertificatePinningClientFactory;
.......public class MainApplication extends Application implements ReactApplication { ....... @Override
public void
onCreate() {
super.onCreate();
SoLoader.init(this,false);
OkHttpClientProvider.setOkHttpClientFactory(new
CertificatePinningClientFactory()); // Add this line

}
.......}

That’s all for android as well.See ! . Android implementation is easy as well .

Thank you for reading this article and hope to see you soon with new one.

--

--