当前位置: 首页 > 软件库 > 手机/移动开发 > >

react-native-keychain

🔑 Keychain Access for React Native
授权协议 MIT License
开发语言 Java
所属分类 手机/移动开发
软件类型 开源软件
地区 不详
投 递 者 狄晟睿
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

react-native-keychain

Keychain/Keystore Access for React Native

Installation

  1. Run yarn add react-native-keychain

    1 a. Only for React Native <= 0.59: $ react-native link react-native-keychain and check MainApplication.java to verify the package was added. See manual installation below if you have issues with react-native link.

  2. Run pod install in ios/ directory to install iOS dependencies.

  3. If you want to support FaceID, add a NSFaceIDUsageDescription entry in your Info.plist.

  4. Re-build your Android and iOS projects.

Usage

import * as Keychain from 'react-native-keychain';

async () => {
  const username = 'zuck';
  const password = 'poniesRgr8';

  // Store the credentials
  await Keychain.setGenericPassword(username, password);

  try {
    // Retrieve the credentials
    const credentials = await Keychain.getGenericPassword();
    if (credentials) {
      console.log(
        'Credentials successfully loaded for user ' + credentials.username
      );
    } else {
      console.log('No credentials stored');
    }
  } catch (error) {
    console.log("Keychain couldn't be accessed!", error);
  }
  await Keychain.resetGenericPassword();
};

See KeychainExample for fully working project example.

Both setGenericPassword and setInternetCredentials are limited to strings only, so if you need to store objects etc, please use JSON.stringify/JSON.parse when you store/access it.

API

setGenericPassword(username, password, [{ accessControl, accessible, accessGroup, service, securityLevel }])

Will store the username/password combination in the secure storage. Resolves to {service, storage} or rejects in case of an error. storage - is a name of used internal cipher for saving secret; service - name used for storing secret in internal storage (empty string resolved to valid default name).

getGenericPassword([{ authenticationPrompt, service, accessControl }])

Will retrieve the username/password combination from the secure storage. Resolves to { username, password, service, storage } if an entry exists or false if it doesn't. It will reject only if an unexpected error is encountered like lacking entitlements or permission.

resetGenericPassword([{ service }])

Will remove the username/password combination from the secure storage. Resolves to true in case of success.

getAllGenericPasswordServices()

Will retrieve all known service names for which a generic password has been stored (e.g., setGenericPassword).

Note: on iOS this will actully read the encrypted entries, so it will trigger an authentication UI if you have encrypted any entries with password/biometry.

setInternetCredentials(server, username, password, [{ accessControl, accessible, accessGroup, securityLevel }])

Will store the server/username/password combination in the secure storage. Resolves to { username, password, service, storage };

hasInternetCredentials(server)

Will check if the username/password combination for server is available in the secure storage. Resolves to true if an entry exists or false if it doesn't.

getInternetCredentials(server, [{ authenticationPrompt }])

Will retrieve the server/username/password combination from the secure storage. Resolves to { username, password } if an entry exists or false if it doesn't. It will reject only if an unexpected error is encountered like lacking entitlements or permission.

resetInternetCredentials(server)

Will remove the server/username/password combination from the secure storage.

requestSharedWebCredentials() (iOS only)

Asks the user for a shared web credential. Requires additional setup both in the app and server side, see Apple documentation. Resolves to { server, username, password } if approved and false if denied and throws an error if not supported on platform or there's no shared credentials.

setSharedWebCredentials(server, username, password) (iOS only)

Sets a shared web credential. Resolves to true when successful.

canImplyAuthentication([{ authenticationType }]) (iOS only)

Inquire if the type of local authentication policy is supported on this device with the device settings the user chose. Should be used in combination with accessControl option in the setter functions. Resolves to true if supported.

getSupportedBiometryType()

On iOS: Get what type of hardware biometry support the device can use for biometric encryption. Resolves to a Keychain.BIOMETRY_TYPE value when supported and enrolled, otherwise null.

On Android: Get what type of Class 3 (strong) biometry support the device has. Resolves to a Keychain.BIOMETRY_TYPE value when supported, otherwise null. In most devices this will return FINGERPRINT (except for Pixel 4 or similar where fingerprint sensor is not present).

This method returns null, if the device haven't enrolled into fingerprint/FaceId. Even though it has hardware for it.

getSecurityLevel([{ accessControl }]) (Android only)

Get security level that is supported on the current device with the current OS. Resolves to Keychain.SECURITY_LEVEL enum value.

Options

Data Structure Properties/Fields

Key Platform Description Default
accessControl All This dictates how a keychain item may be used, see possible values in Keychain.ACCESS_CONTROL. None
accessible iOS only This dictates when a keychain item is accessible, see possible values in Keychain.ACCESSIBLE. Keychain.ACCESSIBLE.WHEN_UNLOCKED
accessGroup iOS only In which App Group to share the keychain. Requires additional setup with entitlements. None
authenticationPrompt All What to prompt the user when unlocking the keychain with biometry or device password. See authenticationPrompt Properties
authenticationType iOS only Policies specifying which forms of authentication are acceptable. Keychain.AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS
service All Reverse domain name qualifier for the service associated with password. App bundle ID
storage Android only Force specific cipher storage usage during saving the password Select best available storage
rules Android only Force following to a specific security rules Keychain.RULES.AUTOMATIC_UPGRADE
authenticationPrompt Properties
Key Platform Description Default
title All Title of the authentication prompt when requesting a stored secret. Authenticate to retrieve secret
subtitle Android only Subtitle of the Android authentication prompt when requesting a stored secret. None. Optional
description Android only Description of the Android authentication prompt when requesting a stored secret. None. Optional
cancel Android only Negative button text of the Android authentication prompt when requesting a stored secret. Cancel

Keychain.ACCESS_CONTROL enum

Key Description
USER_PRESENCE Constraint to access an item with either Touch ID or passcode.
BIOMETRY_ANY Constraint to access an item with Touch ID for any enrolled fingers.
BIOMETRY_CURRENT_SET Constraint to access an item with Touch ID for currently enrolled fingers.
DEVICE_PASSCODE Constraint to access an item with a passcode.
APPLICATION_PASSWORD Constraint to use an application-provided password for data encryption key generation.
BIOMETRY_ANY_OR_DEVICE_PASSCODE Constraint to access an item with Touch ID for any enrolled fingers or passcode.
BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE Constraint to access an item with Touch ID for currently enrolled fingers or passcode.

Note #1: BIOMETRY_ANY, BIOMETRY_CURRENT_SET, BIOMETRY_ANY_OR_DEVICE_PASSCODE, BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE - recognized by Android as a requirement for Biometric enabled storage (Till we got a better implementation);

Note #2: For Android we support only two states: None (default) and Fingerprint (use only biometric protected storage); Face recognition fails with "User not authenticated" exception, see issue #318

Refs:

Keychain.ACCESSIBLE enum

Key Description
WHEN_UNLOCKED The data in the keychain item can be accessed only while the device is unlocked by the user.
AFTER_FIRST_UNLOCK The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.
ALWAYS The data in the keychain item can always be accessed regardless of whether the device is locked.
WHEN_PASSCODE_SET_THIS_DEVICE_ONLY The data in the keychain can only be accessed when the device is unlocked. Only available if a passcode is set on the device. Items with this attribute never migrate to a new device.
WHEN_UNLOCKED_THIS_DEVICE_ONLY The data in the keychain item can be accessed only while the device is unlocked by the user. Items with this attribute do not migrate to a new device.
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user. Items with this attribute never migrate to a new device.
ALWAYS_THIS_DEVICE_ONLY The data in the keychain item can always be accessed regardless of whether the device is locked. Items with this attribute never migrate to a new device.

Refs:

Keychain.AUTHENTICATION_TYPE enum

Key Description
DEVICE_PASSCODE_OR_BIOMETRICS Device owner is going to be authenticated by biometry or device passcode.
BIOMETRICS Device owner is going to be authenticated using a biometric method (Touch ID or Face ID).

Refs:

Keychain.BIOMETRY_TYPE enum

Key Description
TOUCH_ID Device supports authentication with Touch ID. (iOS only)
FACE_ID Device supports authentication with Face ID. (iOS only)
FINGERPRINT Device supports authentication with Fingerprint. (Android only)
FACE Device supports authentication with Face Recognition. (Android only)
IRIS Device supports authentication with Iris Recognition. (Android only)

Refs:

Keychain.SECURITY_LEVEL enum (Android only)

If set, securityLevel parameter specifies minimum security level that the encryption key storage should guarantee for storing credentials to succeed.

Key Description
ANY no security guarantees needed (default value); Credentials can be stored in FB Secure Storage;
SECURE_SOFTWARE requires for the key to be stored in the Android Keystore, separate from the encrypted data;
SECURE_HARDWARE requires for the key to be stored on a secure hardware (Trusted Execution Environment or Secure Environment). Read this article for more information.

Keychain.STORAGE_TYPE enum (Android only)

Key Description
FB Facebook compatibility cipher
AES Encryptions without human interaction.
RSA Encryption with biometrics.

Keychain.SECURITY_RULES enum (Android only)

Key Description
NONE No rules. Be dummy, developer control everything
AUTOMATIC_UPGRADE Upgrade secret to the best available storage as soon as it is available and user request secret extraction. Upgrade not applied till we request the secret.

Important Behavior

Rule 1: Automatic Security Level Upgrade

As a rule library try to apply the best possible encryption and access method for storing secrets.

What does it mean in practical use case?

Scenario #1: User has a new phone and run on it an application with this module and store secret on device.Several days later user configures biometrics on the device and run application again. When the user will try to access the secret, the library will detect security enhancement and will upgrade secret storage to the best possible.


Q: What will happen if user disables/drops biometric usage?

A: User will lose ability to extract secret from storage. On re-enable biometric access to the secret will be possible again.


Q: Is it possible to implement automatic downgrading?

A: From security perspective any Automatic downgrading is treated as "a loss of the trust" point.Developer should implement own logic to allow downgrade and deal with "security loss". (My recommendation - never do that!)


Q: How to disable automatic upgrade?

A: Do call getGenericPassword({ ...otherProps, rules: "none" }) with extra property rules set to none string value.


Q: How to force a specific level of encryption during saving the secret?

A: Do call setGenericPassword({ ...otherProps, storage: "AES" }) with forced storage.

Note: attempt to force storage RSA when biometrics is not available will force code to reject call with errors specific to device biometric configuration state.

Manual Installation

iOS

Option: Manually

  • Right click on Libraries, select Add files to "…" and select node_modules/react-native-keychain/RNKeychain.xcodeproj
  • Select your project and under Build Phases -> Link Binary With Libraries, press the + and select libRNKeychain.a.
  • make sure pod 'RNKeychain' is not in your Podfile

Option: With CocoaPods

Add the following to your Podfile and run pod update:

pod 'RNKeychain', :path => '../node_modules/react-native-keychain'

Enable Keychain Sharing entitlement for iOS 10+

For iOS 10 you'll need to enable the Keychain Sharing entitlement in the Capabilities section of your build target. (See screenshot). Otherwise you'll experience the error shown below.

screen shot 2016-09-16 at 20 56 33

Error: {
  code = "-34018";
  domain = NSOSStatusErrorDomain;
  message = "The operation couldn\U2019t be completed. (OSStatus error -34018.)";
}

Android

Option: Manually

  • Edit android/settings.gradle to look like this (without the +):
rootProject.name = 'MyApp'

include ':app'

+ include ':react-native-keychain'
+ project(':react-native-keychain').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keychain/android')
  • Edit android/app/build.gradle (note: app folder) to look like this:
apply plugin: 'com.android.application'

android {
  ...
}

dependencies {
  implementation fileTree(dir: 'libs', include: ['*.jar'])
  implementation 'com.android.support:appcompat-v7:23.0.1'
  implementation 'com.facebook.react:react-native:0.19.+'
+ implementation project(':react-native-keychain')
}
  • Edit your MainApplication.java (deep in android/app/src/main/java/...) to look like this (note two places to edit):
package com.myapp;

+ import com.oblador.keychain.KeychainPackage;

....

public class MainActivity extends extends ReactActivity {

  @Override
  protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
              new MainReactPackage(),
+             new KeychainPackage()
      );
  }
  ...
}

Proguard Rules

On Android builds that use proguard (like release), you may see the following error:

RNKeychainManager: no keychain entry found for service:
JNI DETECTED ERROR IN APPLICATION: JNI FindClass called with pending exception java.lang.NoSuchFieldError: no "J" field "mCtxPtr" in class "Lcom/facebook/crypto/cipher/NativeGCMCipher;" or its superclasses

If so, add a proguard rule in proguard-rules.pro:

-keep class com.facebook.crypto.** {
   *;
}

Unit Testing with Jest

The keychain manager relies on interfacing with the native application itself. As such, it does not successfully compile and run in the context of a Jest test, where there is no underlying app to communicate with. To be able to call the JS functions exposed by this module in a unit test, you should mock them in one of the following two ways:

First, let's create a mock object for the module:

const keychainMock = {
  SECURITY_LEVEL_ANY: "MOCK_SECURITY_LEVEL_ANY",
  SECURITY_LEVEL_SECURE_SOFTWARE: "MOCK_SECURITY_LEVEL_SECURE_SOFTWARE",
  SECURITY_LEVEL_SECURE_HARDWARE: "MOCK_SECURITY_LEVEL_SECURE_HARDWARE",
  setGenericPassword: jest.fn().mockResolvedValue(),
  getGenericPassword: jest.fn().mockResolvedValue(),
  resetGenericPassword: jest.fn().mockResolvedValue(),
  ...
}

Using a Jest __mocks__ Directory

  1. Read the jest docs for initial setup

  2. Create a react-native-keychain folder in the __mocks__ directory and add index.js file in it. It should contain the following code:

export default keychainMock;

Using a Jest Setup File

  1. In your Jest config, add a reference to a setup file

  2. Inside your setup file, set up mocking for this package:

jest.mock('react-native-keychain', () => keychainMock);

Now your tests should run successfully, though note that writing and reading to the keychain will be effectively a no-op.

Notes

Android Notes

The module will automatically use the appropriate CipherStorage implementation based on API level:

  • API level 16-22 will en/de crypt using Facebook Conceal
  • API level 23+ will en/de crypt using Android Keystore

Encrypted data is stored in SharedPreferences.

The setInternetCredentials(server, username, password) call will be resolved as call to setGenericPassword(username, password, server). Use the server argument to distinguish between multiple entries.

Configuring the Android-specific behavior

Android implementation has behavioural specifics incurred by existing inconsistency between implementations by different vendors. E.g., some Samsung devices show very slow startup of crypto system. To alleviate this, a warm-up strategy is introduced in Android implementation of this library.

Using default constructor you get default behaviour, i.e. with the warming up on.

private List<ReactPackage> createPackageList() {
      return Arrays.asList(
        ...
        new KeychainPackage(),  // warming up is ON
        ...
      )

Those who want finer control are required to use constructor with a builder which can be configured as they like:

private List<ReactPackage> createPackageList() {
      return Arrays.asList(
        ...
        new KeychainPackage(
                new KeychainModuleBuilder()
                        .withoutWarmUp()),   // warming up is OFF
        ...
      )

iOS Notes

If you need Keychain Sharing in your iOS extension, make sure you use the same App Group and Keychain Sharing group names in your Main App and your Share Extension. To then share the keychain between the Main App and Share Extension, use the accessGroup and service option on setGenericPassword and getGenericPassword, like so: getGenericPassword({ accessGroup: 'group.appname', service: 'com.example.appname' })

Refs:

macOS Catalyst

This package supports macOS Catalyst.

Security

On API levels that do not support Android keystore, Facebook Conceal is used to en/decrypt stored data. The encrypted data is then stored in SharedPreferences. Since Conceal itself stores its encryption key in SharedPreferences, it follows that if the device is rooted (or if an attacker can somehow access the filesystem), the key can be obtained and the stored data can be decrypted. Therefore, on such a device, the conceal encryption is only an obscurity. On API level 23+ the key is stored in the Android Keystore, which makes the key non-exportable and therefore makes the entire process more secure. Follow best practices and do not store user credentials on a device. Instead use tokens or other forms of authentication and re-ask for user credentials before performing sensitive operations.

Android Security Framework

Maintainers


Joel Arvidsson

Author

Vojtech Novak

Maintainer

Pelle Stenild Coltau

Maintainer

Oleksandr Kucherenko

Contributor

For Developers / Contributors

License

MIT © Joel Arvidsson 2016-2020

  • 苹果官方对于iOS设备唯一标识的官方文档链接: https://developer.apple.com/reference/uikit/uidevice/1620059-identifierforvendor 近日因为公司app有“一账号一设备”的需求,外包已完成此功能,个人也研究了一下,但发现和外包获取的不一样。所以想在此说明一下,以便大家参考。 设备唯一标识简介: IDFV: 全拼:ident

  • RN版本是0.45。使用的技术栈是:react-native(0.45) + react-redux + redux-saga Android 1. 样式的值不要设置小数,安卓手机不支持。如: style: { padding: 4.5 } 2. 文字垂中位置不要使用lineHeigh控制,安卓不生效。   解决方法:使用padding | margin去控制 3.FlatList、Scrol

  • 文档:网络安全策略 · React Native 中文网 1.简介 在本指南中,将了解存储敏感信息、身份验证、网络安全以及有助于保护应用程序的最佳做法。 2.保存敏感信息 切勿在应用代码中存储敏感的 API 密钥。 任何检查应用程序包的人都可以以纯文本形式访问代码中包含的任何内容。 react-native-dotenv 和 react-native-config 之类的工具非常适合添加环境变量

  • 1.注意:生成签名密钥过程中不要用中文 官网链接: http://reactnative.cn/docs/0.44/signed-apk-android.html#content   2.生成一个签名密钥 你可以用keytool命令生成一个私有密钥。在Windows上keytool命令放在JDK的bin目录中(比如C:\Program Files\Java\jdkx.x.x_x\bin),你可能需

  • 打包APK 本文档贡献者:sunnylqm(100.00%) Android 要求所有应用都有一个数字签名才会被允许安装在用户手机上,所以在把应用发布到类似Google Play store这样的应用市场之前,你需要先生成一个签名的 APK 包。Android 开发者官网上的如何给你的应用签名文档描述了签名的细节。本指南旨在提供一个简化的签名和打包 js 的操作步骤,不会涉及太多理论。 生成一个签

  • React-Native打包签名Android.Apk 1.生成一个签名密钥 你可以用keytool命令生成一个私有密钥。在Windows上keytool命令放在JDK的bin目录中(比如C:\ProgramFiles\Java\jdkx.x.x_x\bin),你可能需要在命令行中先进入那个目录才能执行此命令。 $ keytool -genkey -v -keystoremy-release-ke

  • 前言: 使用Touch ID也称为指纹身份验证在移动应用程序中非常流行。Touch ID功能可保护应用程序并使其成为用户的无缝身份验证流程。 许多银行应用程序,如美国银行,发现,大通,使用Touch ID身份验证,实现安全和无缝的身份验证。 用户无需在每次登录时键入长密码,只需允许他们使用Touch ID登录即可。 使用iPhone X,我们可以使用Face ID身份验证。Touch ID和Fac

  • 前言 大部分内容是复制过来的,主要做了一下整理,方便自己查阅。 打包发布 Android 要求所有应用都有一个数字签名才会被允许安装在用户手机上,所以在把应用发布到应用市场之前,你需要先生成一个签名的 AAB 或 APK 包(Google Play 现在要求 AAB 格式,而国内的应用市场目前仅支持 APK 格式。但无论哪种格式,下面的签名步骤是一样的)。Android 开发者官网上的如何给你的应

  • Android要求所有应用都有一个数字签名才会被允许安装在用户手机上,所以在把应用发布到类似Google Play store这样的应用市场之前,你需要先生成一个签名的APK包。Android开发者官网上的如何给你的应用签名文档描述了签名的细节。本指南旨在提供一个简化的签名和打包js的操作步骤,不会涉及太多理论。 生成一个签名密钥 你可以用keytool命令生成一个私有密钥。在Windows上ke

 相关资料
  • 本文向大家介绍react-native 启动React Native Packager,包括了react-native 启动React Native Packager的使用技巧和注意事项,需要的朋友参考一下 示例 在最新版本的React Native上,无需运行打包程序。它将自动运行。 默认情况下,这将在端口8081上启动服务器。要指定服务器所在的端口            

  • 百度移动统计SDK支持使用react native框架的H5页面统计,封装好的插件已经在github上开源,相关用法具体请参考:https://github.com/BaiduMobileAnalysis/baidumobstat-react-native。

  • The React Native environment has a lot of little quirks, so this documentation is aimed at helping smooth those over. Please feel free to create issues on GitHub for recommendations and additions to t

  • React Native 可以基于目前大热的开源JavaScript库React.js来开发iOS和Android原生App。而且React Native已经用于生产环境——Facebook Groups iOS 应用就是基于它开发的。 React Native的原理是在JavaScript中用React抽象操作系统原生的UI组件,代替DOM元素来渲染,比如以<View>取代<div>,以<Ima

  • 本文向大家介绍react-native setState,包括了react-native setState的使用技巧和注意事项,需要的朋友参考一下 示例 要在应用程序中更改视图,可以使用setState-这将重新渲染您的组件及其任何子组件。setState在新状态和先前状态之间执行浅表合并,并触发组件的重新呈现。 setState 接受键值对象或返回键值对象的函数 键值对象 功能 使用函数对于基于

  • 诸葛io移动统计支持React Native插件,以下为集成方法。 1. 环境准备 1.1. iOS环境 iOS 8.0+ 代码支持iOS8.0的系统 pod 1.0+ iOS系统的集成依赖于cocoaPod工具 1.2. Android环境 Android SDK 16+ 代码支持Android 16+ 1.3. React Native环境 react-native 0.50+ react-n