SSL Pinning in React Native
- General
SSL Pinning in React Native
Before Implementing SSL pinning in our Project, we must have basic knowledge of SSL, how SSL Works.
What is SSL?
- SSL (Secure Sockets Layer), is an encryption-based Internet security protocol.
- It secures the connection & data transfer between two network devices.
- It works under transport layer protocol.
What is an SSL Certificate?
- It is a data file hosted on website server
- It contains some information like:
- Website public key
- website identity
- Issue and expiry date
- and other related information
- It is issued by Certificate authority
HOW SSL Certificate is generated
- The Server first creates a Public and Private key and generates a certificate.
- The Server generates a CSR (Certificate signing request) to CA
- The CA then signs the Certificate with its own private key and issues it.
- The SSL Certification can now be installed on server
How does an SSL Certificate work?
- This process contains two keys:
- Public Key which is publicly distributed by SSL Certificate.
- Private key: which is kept privately by Server
- The data is encrypted by public key and decrypted by private key only.
Steps of SSL Communication:
- Browser request a web page to Server
- Server sends the ssl certificate which contains the public key to browser
- Browsers check the validation of certificates by connecting to CA.
- Once the certificate is validated, browser knows that it can be trusted and a green padlock is displayed by the browser
- Two keys are generated by the client. One key is encrypted by the public key and send to server
- The server uses its private key to decrypt the shared key.
- Now the keys are used by the browser and web server in order to communicate with each other.
How hackers attack SSL?
- If a hacker wants to interpret the data which is under transmission, because it is encrypted, the hacker will get garbage data.
- When we request for a particular website, the hacker interprets and routes the requests to his/her server.
- As the browser dont know the Certificate public key is of the requested server. Browser will normally follow the procedure and seems to be a valid server and starts communicating.
- If the browser already knows the public key then this can be avoided.
What is SSL Pinning & why it can be required?
- SSL pinning is the process of pinning the ssl certificate public key in the app itself.
- During Handshaking if the server public key is different from what is pinned in the app, the transmission will be rejected by the client.
There are two types of SSL Pinning
- Pinning the full certificate: Which required the app to re publish if the certificate expires/
- Pinning the Public Key: Which will not change if it is renewed properly.
Implementation in React Native – Android
In android it is implemented by using okhttp library
There are few steps to be followed:
- Extracting the public key from certificate
1 |
openssl s_client -servername <domain_name> -connect <domain_name>:443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 |
Example public key:
dz0GbS1i4LnBsJwhRw3iuZmVcgqpn+AlxSBRxUbOz0k=
- Pinning this key in React native for Android
React native already used the okhttp library under the hood for performing network calls, it is much simpler to pin it.
In the same folder as your Android app’s MainApplication.java file, create a new Java file and name it SSLPinnerFactory.java, paste in the following content.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package <Your_Package_Name>; import com.facebook.react.modules.network.OkHttpClientFactory; import com.facebook.react.modules.network.OkHttpClientProvider; import okhttp3.CertificatePinner; import okhttp3.OkHttpClient; public class SSLPinnerFactory implements OkHttpClientFactory { private static String hostname = "busdue.com"; public OkHttpClient createNewNetworkModuleClient() { CertificatePinner certificatePinner = new CertificatePinner.Builder() .add(hostname, "sha256/dz0GbS1i4LnBsJwhRw3iuZmVcgqpn+AlxSBRxUbOz0k=") .build(); // Get a OkHttpClient builder with all the React Native defaults OkHttpClient.Builder clientBuilder = OkHttpClientProvider.createClientBuilder(); return clientBuilder .certificatePinner(certificatePinner) .build(); } } |
Add the following line in onCreate Method in MainApplication.java
1 |
OkHttpClientProvider.setOkHttpClientFactory(new SSLPinnerFactory()); |
Add the following import method in MainApplication.java
1 |
import com.facebook.react.modules.network.OkHttpClientProvider; |
- Sample React Native Code App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
import React, {useState} from 'react'; import {StyleSheet, View, Text, Button, Platform} from 'react-native'; const URL = 'https://google.com'; const App: () => React$Node = () => { const [validationMsg, setValidationMsg] = useState('Waiting'); const [validationStatus, setValidationStatus] = useState(''); const onConnectPress = () => { fetch(URL) .then(res => { console.log('**************'); console.log(res); console.log('**************'); setValidationMsg('Valid certificate, connected.'); setValidationStatus('success'); }) .catch(() => { setValidationMsg('Certificate does not match, connection refused'); setValidationStatus('failed'); }); }; return ( <View style={styles.container}> <Text style={styles.title}>React Native SSL Pinning</Text> <Text style={styles.title}>({Platform.OS.toUpperCase()})</Text> <Text style={styles.header}>Certificate status:</Text> <Text style={[ styles.status, validationStatus === 'success' && styles.success, validationStatus === 'failed' && styles.failed, ]}> {validationMsg} </Text> <View style={styles.btnContainer}> <Button title={`Test ${URL}`} onPress={onConnectPress} /> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24, }, title: { fontSize: 24, fontWeight: 'bold', textAlign: 'center', }, header: { paddingTop: 46, fontSize: 18, textAlign: 'center', }, status: { fontSize: 18, fontWeight: 'bold', textAlign: 'center', }, success: { fontSize: 18, fontWeight: 'bold', color: 'green', }, failed: { fontSize: 18, fontWeight: 'bold', color: 'red', }, btnContainer: { borderWidth: 1, borderColor: 'grey', borderRadius: 4, paddingHorizontal: 16, marginTop: 24, }, }); export default App; |
Warning
Pinning certificates limits your server team’s abilities to update their TLS certificates. By pinning certificates, you take on additional operational complexity and limit your ability to migrate between certificate authorities.
To be done
Implementation in IOS
Library for ssl pinning in ios is AF Networking
Sample Code
Ref:
https://itnext.io/react-native-security-ssl-pinning-cde086210d58
Related content
Auriga: Leveling Up for Enterprise Growth!
Auriga’s journey began in 2010 crafting products for India’s