This package generates an RSA key and stores it in the OS vault. It can be used to sign payloads, such as a JWT token.
A common use case is for user authentication. The private key is stored in the OS vault and is secure. The public key (which is in X.509 PEM format) can be sent to the server/back-end. The app then creates a payload (such as a JWT token) and signs it with the private key. The server can validate the signature using the public key. Because only this specific device and app have access to the private key, the server can trust that the payload came from the user and no one else.
This was a simplified explanation of the authentication scenario. Take care when implementing security features!
The length of the RSA key is 3072. Currently, the package doesn't allow you to adjust it.
It stores the key pair in:
- iOS: Keychain
- Android (API level >= 18): Keystore
- Android (API level <= 17): SQLite
The signing algorithm is SHA256withRSA, which uses PKCS#1 for padding.
This package has been in use in production by Movio since 2018. So, it's quite stable. We may be a bit opinionated about what features we want to add or what PRs we accept, as we want to keep the stability in our products.
It requires React Native >= 0.71.0
Simply install it using your package manager. For npm:
npm install react-native-rsa-signer
For iOS, you need to $ cd ios && pod install.
This plugin uses Swift. If you don't use Swift in your iOS project, you need to add a empty.swift file in your project to activate the Swift compiling.
- open your project in Xcode
- right click your project's folder in the Project Navigator, select
New File... - select the
Swift Filetemplate, clickNext - set file name to
empty.swift, make sure your project is enabled inTargets, clickCreate - remove all contents of file
empty.swift - in the
Build Settingsof your project, selectAlways Embed Swift Standard Librariesand setSwift Language Version = Swift 4.0
regenerateKey(alias: string): Promise<string>
Deletes the key pair associated with the given alias (if existed) and generates a new key pair. Returns the public key in X.509 PEM format.
alias is the name for the key pair. You can have multiple key pairs stored. To retrieve one, you need to pass the same alias.
getPublicKey(alias: string): Promise<string>
Returns the Public Key associated with the alias in X.509 PEM format. Returns null if no key pair is existed for this alias.
sign(alias: string, data: string): Promise<string>
Signs data with the private key associated with alias. Returns the signature in base64 format.
Will throw error if there's no key with this alias.
import RNRsaSigner from "react-native-rsa-signer";
const alias = "login-key";
// drop the current key pair for alias, generate a new pair, store it in the key chain and return the PEM string.
const pubKeyPem: Promise<string> = RNRsaSigner.regenerateKey(alias);
// Or you can retrieve and existing key previously stored with the same alias.
// const pubKeyPem: Promise<string> = RNRsaSigner.getPublicKey(alias);
// sign a text with the private key that is stored in the key chain with the provided alias.
const signature: Promise<string> = RNRsaSigner.sign(alias, "my text to sign");A sample code of how you can validate the signature using Bouncy Castle lib in Scala.
// register BouncyCastle JCE provider
java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider())
// read user's key, e.g. stored in database, provided by user during sign up
val key: IntputStream = ???
val factory = java.security.KeyFactory.getInstance("RSA", "BC")
val pr = new org.bouncycastle.util.io.pem.PemReader(new java.io.InputStreamReader(key))
val pubKeySpec = new java.security.spec.X509EncodedKeySpec(pr.readPemObject().getContent())
val publicKey = factory.generatePublic(pubKeySpec).asInstanceOf[java.security.interfaces.RSAPublicKey]
// validate message
val message: byte[] = ???
val signature: byte[] = ???
val sig = java.security.Signature.getInstance("SHA256withRSA");
sig.initVerify(publicKey);
sig.update(message);
val isValid = sig.verify(signature)npm install then open ios/RNRsaSigner.xcodeproj in Xcode.
Build problems to do with `Build input file cannot be found ... third-party/double-conversion-* : Seems to happen for Xcode 10+: facebook/react-native#21168
Fix by:
$ cd node_modules/react-native/scripts && ./ios-install-third-party.sh && cd ../../../
$ cd node_modules/react-native/third-party/glog-0.3.4/ && ../../scripts/ios-configure-glog.sh && cd ../../../../