Compare commits

...

68 Commits

Author SHA1 Message Date
Marcos Rodriguez Vélez
2076b4849e
Merge branch 'pradeep1991singh:master' into master
Some checks failed
CodeQL / Analyze (java) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (ruby) (push) Has been cancelled
2023-02-28 21:30:50 -04:00
pradeep singh
80c35ae524
Update package.json 2022-08-18 08:20:45 +05:30
pradeep singh
5534340fad
Merge pull request #110 from aiden-petersen/support-autolink
Support auto-linking
2022-08-16 18:47:43 +05:30
Aiden
863fbcaf1b Support auto-linking 2022-07-26 20:25:11 +12:00
pradeep singh
6dcf954aab
Create codeql-analysis.yml 2022-05-23 10:44:12 +05:30
pradeep singh
9746bf57a2
Merge pull request #107 from sayurimizuguchi/master
Change priority to use MavenCentral instead of JCenter since it became read-only and it is often offline.
2022-05-23 10:39:15 +05:30
Sayuri Mizuguchi
14f7846144
Merge pull request #1 from sayurimizuguchi/adhoc/fix-jcenter-issues
add mavenCentral as priority for repos than jcenter
2022-05-09 23:48:42 -04:00
Sayuri Mizuguchi
51e040873f
add mavenCentral as priority for repos than jcenter
JCenter has been offline often and it is causing pipeline issues when trying to download the poms/jars. 
Since JCenter also serves as a mirror for Maven Central, and any dependencies available on Maven Central are also available on JCenter, it is better to rely on Maven Central since Gradle team is discouraging the use of JCenter since it became read-only.
2022-05-09 23:46:50 -04:00
pradeep singh
8e8a850a78
Merge pull request #97 from r3nya/patch-1
fix: Xcode 12 compatibility
2022-01-17 12:24:20 +05:30
Andrew M
2368c865c9
fix: Xcode 12 compatibility 2021-07-06 22:20:50 +03:00
marcosrdz
63ab38c9d3 Update RNSecureKeyStore.m 2021-05-22 18:55:27 -04:00
Marcos Rodriguez Vélez
4828fd1a67
Update RNSecureKeyStore.m 2020-11-13 14:10:13 -05:00
pradeep singh
c36726fd58
Merge pull request #87 from tombailey/improve-example-app
Improve example app
2020-10-03 23:30:42 +05:30
pradeep singh
4bb26d8907
Merge pull request #86 from tombailey/master
Use encrypted shared preferences from androidx.security
2020-10-03 23:29:45 +05:30
Tom Bailey
60fab025ff Improve example app 2020-10-03 15:29:35 +09:00
Tom Bailey
29ac5639cc Use encrypted shared preferences from androidx.security 2020-10-03 14:45:37 +09:00
pradeep singh
a054f16807
Update package.json 2020-08-09 13:22:26 +05:30
pradeep singh
133a1a93cf
Merge pull request #84 from oceanbit-dev/master
Made "getPlainText" a public method for use in native code
2020-08-09 13:21:18 +05:30
Corbin Crutchley
08285e25bc Made "getPlainText" a public method for use in native code 2020-08-08 14:12:27 -07:00
pradeep singh
aedb1b95af
Merge pull request #80 from davidgovea/enum-typefix
Fix type definition
2020-08-08 17:02:18 +05:30
David Govea
e681d0a7e2 fix: update type signature of set() - third argument is an options object 2020-08-06 15:07:58 -07:00
pradeep singh
c331182f4a
Update package.json 2020-08-05 23:12:46 +05:30
pradeep singh
342a4876fd
Merge pull request #79 from pradeep1991singh/dependabot/npm_and_yarn/example/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19 in /example
2020-08-05 23:07:04 +05:30
pradeep singh
b18c68b37e
Merge pull request #82 from davidgovea/fix-example-app
Fix example app
2020-08-05 23:06:07 +05:30
pradeep singh
30c26e5b27
Merge pull request #83 from davidgovea/android-targetsdk-update
Allow consuming apps to set android build settings
2020-08-05 23:05:27 +05:30
David Govea
daf8291540 fix(example): fix metro bundling issues with metro.config.js in example app 2020-07-28 10:27:26 -07:00
David Govea
2996abb4de fix(example): enable AndroidX
Technically, `androidx.annotation:annotation` should be included in the
library's build.gradle, since it is used in java sourcecode.
2020-07-28 10:27:01 -07:00
David Govea
9d9dc01487 chore: use safeExtGet approach to prioritize project-level android build settings 2020-07-27 22:07:47 -07:00
David Govea
6c5bcef97a fix(types): update const initializer to enum in typedef 2020-07-27 20:59:36 -07:00
dependabot[bot]
2b66799a51
Bump lodash from 4.17.15 to 4.17.19 in /example
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-16 18:05:23 +00:00
pradeep singh
4ba25dedb3
Update package.json 2020-05-02 12:04:31 +05:30
pradeep singh
97668bdf81
Buy me a coffee ;-) 2020-04-18 18:35:06 +05:30
pradeep singh
b885b2e375
Merge pull request #75 from pradeep1991singh/dependabot/npm_and_yarn/example/acorn-5.7.4
Bump acorn from 5.7.3 to 5.7.4 in /example
2020-03-24 10:20:01 +05:30
dependabot[bot]
03e8b4b47a
Bump acorn from 5.7.3 to 5.7.4 in /example
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-14 01:21:23 +00:00
pradeep singh
67a44276cb
Release 2.0.7 2020-02-25 16:55:43 +05:30
pradeep singh
1c3749d08f
Merge pull request #69 from Alph4Four/master
fix for accessibleValue conflict with KeyChainManager
2020-02-25 16:54:20 +05:30
Alph4Four
8ea8ac2cdb
Fix compatibility issue with RNKeyChainManager
accessibleValue is used by RNKeyChainManager and RNSecureKeyStore and this causes conflict between the two. In this file I replaced accessibleValue by accessibleVal, works just fine without conflicts.
2019-12-30 12:50:07 +00:00
Alph4Four
74cdbd2e0c
Deleted RNSecureKeyStore.m
To upload a new file.
2019-12-30 12:47:29 +00:00
pradeep singh
586e1734ac
Merge pull request #67 from pradeep1991singh/dependabot/npm_and_yarn/example/handlebars-4.5.3
Bump handlebars from 4.1.2 to 4.5.3 in /example
2019-12-30 15:37:51 +05:30
dependabot[bot]
caa59d0b43
Bump handlebars from 4.1.2 to 4.5.3 in /example
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.1.2 to 4.5.3.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.1.2...v4.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2019-12-27 23:56:05 +00:00
pradeep singh
53cbeb2255
Merge pull request #66 from shayantabatabaee/master
fix: Fix an issue to generating keys in some android devices in FA an AR
2019-11-13 18:09:29 +05:30
shayan tabatabaee
3cc49cf7c1 fix: Fix an issue to generating keys in some android devices in FA an AR 2019-11-13 12:08:42 +03:30
pradeep singh
dd8597dbaa
Merge pull request #65 from SaeedZhiany/patch-2
added type definition file to package.json
2019-11-11 19:14:02 +05:30
pradeep singh
680a027711
Merge pull request #64 from SaeedZhiany/patch-1
Load Android Gradle Plugin conditionally
2019-11-11 19:12:28 +05:30
SaeedZhiany
cd6b422545
added type definition file to package.json 2019-11-11 16:27:47 +03:30
SaeedZhiany
3bc02010d9
Load Android Gradle Plugin conditionally 2019-11-11 16:23:20 +03:30
pradeep singh
7e89d793b6
Merge pull request #62 from Javi/patch-1
Change "compile" into "implementation" to avoid warning in Android.
2019-10-12 19:53:37 +05:30
Javier Casaubón
cf7919a93e
Change "compile" into "implementation" to avoid warning in Android.
>INFO: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
2019-10-11 02:59:44 -03:00
pradeep singh
b82e280996
Update package.json 2019-10-03 23:31:58 +05:30
pradeep singh
a259d4dbb1
Update package.json 2019-10-03 23:25:10 +05:30
pradeep singh
d35569e928
Update package.json 2019-09-24 22:59:09 +05:30
pradeep singh
1f2edcac6e
Merge pull request #61 from TalaikisInc/master
fix: RN 0.60+
2019-09-18 22:56:17 +05:30
Tadas Talaikis
ac5168a638
fix: RN 0.60+ 2019-09-18 15:43:20 +03:00
pradeep singh
c3694a9c3e
Merge pull request #60 from pradeep1991singh/dependabot/npm_and_yarn/example/mixin-deep-1.3.2
Bump mixin-deep from 1.3.1 to 1.3.2 in /example
2019-08-29 17:23:53 +05:30
dependabot[bot]
7e0d21f63f
Bump mixin-deep from 1.3.1 to 1.3.2 in /example
Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/jonschlinkert/mixin-deep/releases)
- [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-28 22:46:36 +00:00
pradeep singh
dcf5a581d4
Update FUNDING.yml 2019-08-26 12:29:14 +05:30
pradeep singh
bb4d5eb683
Merge pull request #58 from pradeep1991singh/dependabot/npm_and_yarn/example/lodash-4.17.15
Bump lodash from 4.17.11 to 4.17.15 in /example
2019-08-23 17:45:47 +05:30
pradeep singh
8507b91792
Merge pull request #59 from pradeep1991singh/dependabot/npm_and_yarn/example/js-yaml-3.13.1
Bump js-yaml from 3.12.1 to 3.13.1 in /example
2019-08-23 17:44:56 +05:30
dependabot[bot]
675d151be8
Bump js-yaml from 3.12.1 to 3.13.1 in /example
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.12.1 to 3.13.1.
- [Release notes](https://github.com/nodeca/js-yaml/releases)
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.12.1...3.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-23 12:09:07 +00:00
dependabot[bot]
2726d6fe76
Bump lodash from 4.17.11 to 4.17.15 in /example
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.15.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.15)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-23 12:08:54 +00:00
pradeep singh
84d53a9fa6
Merge pull request #57 from pradeep1991singh/dependabot/npm_and_yarn/example/handlebars-4.1.2
Bump handlebars from 4.0.12 to 4.1.2 in /example
2019-08-23 17:37:26 +05:30
pradeep singh
e883a89fda
Create SECURITY.md 2019-08-23 17:36:14 +05:30
dependabot[bot]
4a879a2c63
Bump handlebars from 4.0.12 to 4.1.2 in /example
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.0.12 to 4.1.2.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.0.12...v4.1.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-23 12:05:48 +00:00
pradeep singh
e5618b9592
Update FUNDING.yml 2019-08-21 19:51:56 +05:30
pradeep singh
e01856d2e9
Update FUNDING.yml 2019-08-21 19:34:57 +05:30
pradeep singh
2bda4f8395
Create FUNDING.yml 2019-08-21 19:24:00 +05:30
pradeep singh
6af285a33a
Merge pull request #53 from pradeep1991singh/santiagofm-patch-1-1
Adds typescript types
2019-08-14 18:26:06 +05:30
pera
72cab06a05
Adds typescript types 2019-08-12 13:56:45 -03:00
18 changed files with 346 additions and 344 deletions

12
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [pradeep1991singh]
patreon: live2code
# open_collective: # Replace with a single Open Collective username
# ko_fi: # Replace with a single Ko-fi username
# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
# liberapay: # Replace with a single Liberapay username
# issuehunt: # Replace with a single IssueHunt username
# otechie: # Replace with a single Otechie username
# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

72
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,72 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '40 9 * * 5'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java', 'javascript', 'ruby' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@ -14,12 +14,6 @@ or
$ yarn add react-native-secure-key-store
```
### Mostly automatic installation
```sh
$ react-native link react-native-secure-key-store
```
### Manual installation
@ -118,3 +112,6 @@ Permission to use, copy, modify, and/or distribute this software for any purpose
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
[![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/ps91)

21
SECURITY.md Normal file
View File

@ -0,0 +1,21 @@
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 5.1.x | :white_check_mark: |
| 5.0.x | :x: |
| 4.0.x | :white_check_mark: |
| < 4.0 | :x: |
## Reporting a Vulnerability
Use this section to tell people how to report a vulnerability.
Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.

View File

@ -1,24 +1,37 @@
def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
buildscript {
repositories {
google()
jcenter()
}
// The Android Gradle plugin is only required when opening the android folder stand-alone.
// This avoids unnecessary downloads and potential conflicts when the library is included as a
// module dependency in an application project.
if (project == rootProject) {
repositories {
google()
mavenCentral()
// JCenter is going read-only repository indefinitely
// Gradle is discouraging jcenter to avoid to avoid build issues - pipeline
// ref: https://blog.gradle.org/jcenter-shutdown
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
dependencies {
classpath("com.android.tools.build:gradle:3.5.2")
}
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
compileSdkVersion safeExtGet('compileSdkVersion', 28)
buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3')
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
minSdkVersion safeExtGet('minSdkVersion', 23)
targetSdkVersion safeExtGet('targetSdkVersion', 28)
versionCode 1
versionName "1.0"
}
@ -29,10 +42,11 @@ android {
repositories {
google()
jcenter()
mavenCentral()
jcenter()
}
dependencies {
compile 'com.facebook.react:react-native:+'
implementation 'com.facebook.react:react-native:+'
implementation "androidx.security:security-crypto:1.0.0-rc03"
}

View File

@ -6,37 +6,23 @@
package com.reactlibrary.securekeystore;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.security.KeyPairGeneratorSpec;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKeys;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Calendar;
import android.support.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.x500.X500Principal;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class RNSecureKeyStoreModule extends ReactContextBaseJavaModule {
@ -55,7 +41,7 @@ public class RNSecureKeyStoreModule extends ReactContextBaseJavaModule {
@ReactMethod
public void set(String alias, String input, @Nullable ReadableMap options, Promise promise) {
try {
setCipherText(alias, input);
getSecureSharedPreferences().edit().putString(alias, input).commit();
promise.resolve("stored ciphertext in app storage");
} catch (Exception e) {
e.printStackTrace();
@ -64,86 +50,26 @@ public class RNSecureKeyStoreModule extends ReactContextBaseJavaModule {
}
}
private PublicKey getOrCreatePublicKey(String alias) throws GeneralSecurityException, IOException {
KeyStore keyStore = KeyStore.getInstance(getKeyStore());
keyStore.load(null);
if (!keyStore.containsAlias(alias) || keyStore.getCertificate(alias) == null) {
Log.i(Constants.TAG, "no existing asymmetric keys for alias");
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 50);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getContext())
.setAlias(alias)
.setSubject(new X500Principal("CN=" + alias))
.setSerialNumber(BigInteger.ONE)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", getKeyStore());
generator.initialize(spec);
generator.generateKeyPair();
Log.i(Constants.TAG, "created new asymmetric keys for alias");
}
return keyStore.getCertificate(alias).getPublicKey();
}
private byte[] encryptRsaPlainText(PublicKey publicKey, byte[] plainTextBytes) throws GeneralSecurityException, IOException {
Cipher cipher = Cipher.getInstance(Constants.RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return encryptCipherText(cipher, plainTextBytes);
}
private byte[] encryptAesPlainText(SecretKey secretKey, String plainText) throws GeneralSecurityException, IOException {
Cipher cipher = Cipher.getInstance(Constants.AES_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return encryptCipherText(cipher, plainText);
}
private byte[] encryptCipherText(Cipher cipher, String plainText) throws GeneralSecurityException, IOException {
return encryptCipherText(cipher, plainText.getBytes("UTF-8"));
}
private byte[] encryptCipherText(Cipher cipher, byte[] plainTextBytes) throws GeneralSecurityException, IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
cipherOutputStream.write(plainTextBytes);
cipherOutputStream.close();
return outputStream.toByteArray();
}
private SecretKey getOrCreateSecretKey(String alias) throws GeneralSecurityException, IOException {
try {
return getSymmetricKey(alias);
} catch (FileNotFoundException fnfe) {
Log.i(Constants.TAG, "no existing symmetric key for alias");
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
//32bytes / 256bits AES key
keyGenerator.init(256);
SecretKey secretKey = keyGenerator.generateKey();
PublicKey publicKey = getOrCreatePublicKey(alias);
Storage.writeValues(getContext(), Constants.SKS_KEY_FILENAME + alias,
encryptRsaPlainText(publicKey, secretKey.getEncoded()));
Log.i(Constants.TAG, "created new symmetric keys for alias");
return secretKey;
}
}
private void setCipherText(String alias, String input) throws GeneralSecurityException, IOException {
Storage.writeValues(getContext(), Constants.SKS_DATA_FILENAME + alias,
encryptAesPlainText(getOrCreateSecretKey(alias), input));
private SharedPreferences getSecureSharedPreferences() throws GeneralSecurityException, IOException {
return EncryptedSharedPreferences.create(
"secret_shared_prefs",
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
reactContext,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
}
@ReactMethod
public void get(String alias, Promise promise) {
try {
promise.resolve(getPlainText(alias));
String value = getSecureSharedPreferences().getString(alias, null);
if (value == null) {
//throw FileNotFoundException to keep match old behaviour when a value is missing
throw new FileNotFoundException(alias + " has not been set");
} else {
promise.resolve(value);
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
promise.reject("404", "{\"code\":404,\"api-level\":" + Build.VERSION.SDK_INT + ",\"message\":" + fnfe.getMessage() + "}", fnfe);
@ -154,73 +80,15 @@ public class RNSecureKeyStoreModule extends ReactContextBaseJavaModule {
}
}
private PrivateKey getPrivateKey(String alias) throws GeneralSecurityException, IOException {
KeyStore keyStore = KeyStore.getInstance(getKeyStore());
keyStore.load(null);
return (PrivateKey) keyStore.getKey(alias, null);
}
private byte[] decryptRsaCipherText(PrivateKey privateKey, byte[] cipherTextBytes) throws GeneralSecurityException, IOException {
Cipher cipher = Cipher.getInstance(Constants.RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return decryptCipherText(cipher, cipherTextBytes);
}
private byte[] decryptAesCipherText(SecretKey secretKey, byte[] cipherTextBytes) throws GeneralSecurityException, IOException {
Cipher cipher = Cipher.getInstance(Constants.AES_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return decryptCipherText(cipher, cipherTextBytes);
}
private byte[] decryptCipherText(Cipher cipher, byte[] cipherTextBytes) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(cipherTextBytes);
CipherInputStream cipherInputStream = new CipherInputStream(bais, cipher);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[256];
int bytesRead = cipherInputStream.read(buffer);
while (bytesRead != -1) {
baos.write(buffer, 0, bytesRead);
bytesRead = cipherInputStream.read(buffer);
}
return baos.toByteArray();
}
private SecretKey getSymmetricKey(String alias) throws GeneralSecurityException, IOException {
byte[] cipherTextBytes = Storage.readValues(getContext(), Constants.SKS_KEY_FILENAME + alias);
return new SecretKeySpec(decryptRsaCipherText(getPrivateKey(alias), cipherTextBytes), Constants.AES_ALGORITHM);
}
private String getPlainText(String alias) throws GeneralSecurityException, IOException {
SecretKey secretKey = getSymmetricKey(alias);
byte[] cipherTextBytes = Storage.readValues(getContext(), Constants.SKS_DATA_FILENAME + alias);
return new String(decryptAesCipherText(secretKey, cipherTextBytes), "UTF-8");
}
@ReactMethod
public void remove(String alias, Promise promise) {
Storage.resetValues(getContext(), new String[] {
Constants.SKS_DATA_FILENAME + alias,
Constants.SKS_KEY_FILENAME + alias,
});
promise.resolve("cleared alias");
}
private Context getContext() {
return getReactApplicationContext();
}
private String getKeyStore() {
try {
KeyStore.getInstance(Constants.KEYSTORE_PROVIDER_1);
return Constants.KEYSTORE_PROVIDER_1;
} catch (Exception err) {
try {
KeyStore.getInstance(Constants.KEYSTORE_PROVIDER_2);
return Constants.KEYSTORE_PROVIDER_2;
} catch (Exception e) {
return Constants.KEYSTORE_PROVIDER_3;
}
getSecureSharedPreferences().edit().remove(alias).commit();
promise.resolve("cleared alias");
} catch (Exception e) {
e.printStackTrace();
Log.e(Constants.TAG, "Exception: " + e.getMessage());
promise.reject("{\"code\":6,\"api-level\":" + Build.VERSION.SDK_INT + ",\"message\":" + e.getMessage() + "}");
}
}
}

View File

@ -1,38 +0,0 @@
package com.reactlibrary.securekeystore;
// Helper function for storing keys to internal storage.
import android.content.Context;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public final class Storage {
public static void writeValues(Context context, String filename, byte[] bytes) throws IOException {
FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
fos.write(bytes);
fos.close();
}
public static byte[] readValues(Context context, String filename) throws IOException {
FileInputStream fis = context.openFileInput(filename);
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead = fis.read(buffer);
while(bytesRead != -1) {
baos.write(buffer, 0, bytesRead);
bytesRead = fis.read(buffer);
}
return baos.toByteArray();
}
public static void resetValues(Context context, String[] filenames) {
for(String filename : filenames) {
context.deleteFile(filename);
}
}
}

View File

@ -8,68 +8,81 @@
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {Platform, StyleSheet, Button, Text, TextInput, View} from 'react-native';
import RNSecureKeyStore, {ACCESSIBLE} from "react-native-secure-key-store";
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
type Props = {};
export default class App extends Component<Props> {
state = {
alias: 'hello',
value: 'world'
};
getValue() {
RNSecureKeyStore.get(this.state.alias)
.then((value) => {
this.setState({
value,
});
})
.catch(console.error);
}
setValue() {
RNSecureKeyStore.set(this.state.alias, this.state.value, {})
.then(() => this.getValue())
.catch(console.error);
}
removeValue() {
RNSecureKeyStore.remove(this.state.alias)
.then(() => this.getValue())
.catch(console.error);
}
render() {
RNSecureKeyStore.set("key1", "value1", {accessible: ACCESSIBLE.ALWAYS_THIS_DEVICE_ONLY})
.then((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
RNSecureKeyStore.set("key2", "value2", {accessible: ACCESSIBLE.ALWAYS_THIS_DEVICE_ONLY})
.then((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
RNSecureKeyStore.get("key1")
.then((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
RNSecureKeyStore.get("key2")
.then((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
RNSecureKeyStore.remove("key1")
.then((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
RNSecureKeyStore.remove("key2")
.then((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
<View style={styles.row}>
<Text>Alias:</Text>
<TextInput
style={styles.textInput}
onChangeText={alias => this.setState({alias})}
value={this.state.alias}
/>
</View>
<View style={styles.row}>
<Text>Value:</Text>
<TextInput
style={styles.textInput}
onChangeText={value => this.setState({value})}
value={this.state.value}
/>
</View>
<View style={styles.row}>
<View style={styles.button}>
<Button
onPress={() => this.getValue()}
title='Get'
/>
</View>
<View style={styles.button}>
<Button
onPress={() => this.setValue()}
title='Set'
/>
</View>
<View style={styles.button}>
<Button
onPress={() => this.removeValue()}
title='Remove'
/>
</View>
</View>
</View>
);
}
@ -82,14 +95,20 @@ const styles = StyleSheet.create({
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
row: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginTop: 20
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
textInput: {
height: 40,
width: 200,
borderColor: 'gray',
borderWidth: 1,
marginLeft: 10
},
button: {
marginLeft: 10
}
});

View File

@ -3,7 +3,7 @@
buildscript {
ext {
buildToolsVersion = "28.0.2"
minSdkVersion = 16
minSdkVersion = 23
compileSdkVersion = 28
targetSdkVersion = 27
supportLibVersion = "28.0.0"

View File

@ -16,3 +16,5 @@
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.useAndroidX=true
android.enableJetifier=true

12
example/metro.config.js Normal file
View File

@ -0,0 +1,12 @@
const path = require("path");
const packagePath = path.resolve(__dirname, "../");
module.exports = {
resolver: {
extraNodeModules: {
"react-native-secure-key-store": packagePath,
},
},
watchFolders: [packagePath],
};

View File

@ -9,7 +9,7 @@
"dependencies": {
"react": "16.6.3",
"react-native": "0.58.1",
"react-native-secure-key-store": "../../react-native-secure-key-store"
"react-native-secure-key-store": "file:.."
},
"devDependencies": {
"babel-core": "^7.0.0-bridge.0",

View File

@ -684,9 +684,9 @@ acorn-walk@^6.0.1:
integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==
acorn@^5.5.3:
version "5.7.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
version "5.7.4"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
acorn@^6.0.1:
version "6.0.5"
@ -920,7 +920,7 @@ async-limiter@~1.0.0:
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
async@^2.4.0, async@^2.5.0, async@^2.6.1:
async@^2.4.0, async@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==
@ -1341,10 +1341,10 @@ commander@~2.13.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==
commander@~2.17.1:
version "2.17.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
commander@~2.20.3:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commondir@^1.0.1:
version "1.0.1"
@ -2234,11 +2234,11 @@ growly@^1.3.0:
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
handlebars@^4.0.11:
version "4.0.12"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5"
integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==
version "4.5.3"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482"
integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==
dependencies:
async "^2.5.0"
neo-async "^2.6.0"
optimist "^0.6.1"
source-map "^0.6.1"
optionalDependencies:
@ -3144,9 +3144,9 @@ jest@24.0.0:
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^3.12.0, js-yaml@^3.9.0:
version "3.12.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600"
integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
@ -3389,9 +3389,9 @@ lodash.throttle@^4.1.1:
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.6.1:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
version "4.17.19"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
version "1.4.0"
@ -3822,9 +3822,9 @@ minizlib@^1.1.1:
minipass "^2.2.1"
mixin-deep@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe"
integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==
version "1.3.2"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
dependencies:
for-in "^1.0.2"
is-extendable "^1.0.1"
@ -3903,6 +3903,11 @@ negotiator@0.6.1:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
neo-async@^2.6.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
@ -5525,11 +5530,11 @@ uglify-es@^3.1.9:
source-map "~0.6.1"
uglify-js@^3.1.4:
version "3.4.9"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==
version "3.7.3"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a"
integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg==
dependencies:
commander "~2.17.1"
commander "~2.20.3"
source-map "~0.6.1"
ultron@1.0.x:

23
index.d.ts vendored Normal file
View File

@ -0,0 +1,23 @@
declare module 'react-native-secure-key-store' {
export enum ACCESSIBLE {
AFTER_FIRST_UNLOCK = 'AccessibleAfterFirstUnlock',
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY =
'AccessibleAfterFirstUnlockThisDeviceOnly',
ALWAYS = 'AccessibleAlways',
ALWAYS_THIS_DEVICE_ONLY = 'AccessibleAlwaysThisDeviceOnly',
WHEN_PASSCODE_SET_THIS_DEVICE_ONLY =
'AccessibleWhenPasscodeSetThisDeviceOnly',
WHEN_UNLOCKED = 'AccessibleWhenUnlocked',
WHEN_UNLOCKED_THIS_DEVICE_ONLY = 'AccessibleWhenUnlockedThisDeviceOnly',
}
interface RNSecureKeyStore {
get: (key: string) => Promise<any>
set: (key: string, value: string, options?: { accessible?: ACCESSIBLE }) => Promise<any>
remove: (key: string) => Promise<any>
setResetOnAppUninstallTo: (enabled: boolean) => boolean
}
const secureKeystore: RNSecureKeyStore
export default secureKeystore
}

View File

@ -74,7 +74,7 @@ static NSString *serviceName = @"RNSecureKeyStoreKeyChain";
}
- (BOOL)createKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier options: (NSDictionary * __nullable)options {
CFStringRef accessible = accessibleValue(options);
CFStringRef accessible = accessibleVal(options);
NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];
NSData *valueData = [value dataUsingEncoding:NSUTF8StringEncoding];
@ -91,7 +91,7 @@ static NSString *serviceName = @"RNSecureKeyStoreKeyChain";
- (BOOL)updateKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier options:(NSDictionary * __nullable)options {
CFStringRef accessible = accessibleValue(options);
CFStringRef accessible = accessibleVal(options);
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
@ -128,15 +128,6 @@ static NSString *serviceName = @"RNSecureKeyStoreKeyChain";
}
}
- (void)handleAppUninstallation
{
if ([self resetOnAppUninstall] && ![[NSUserDefaults standardUserDefaults] boolForKey:@"RnSksIsAppInstalled"]) {
[self clearSecureKeyStore];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"RnSksIsAppInstalled"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
NSError * secureKeyStoreError(NSString *errMsg)
{
NSError *error = [NSError errorWithDomain:serviceName code:200 userInfo:@{@"reason": errMsg}];
@ -155,7 +146,6 @@ RCT_EXPORT_METHOD(set: (NSString *)key value:(NSString *)value
rejecter:(RCTPromiseRejectBlock)reject)
{
@try {
[self handleAppUninstallation];
BOOL status = [self createKeychainValue: value forIdentifier: key options: options];
if (status) {
resolve(@"key stored successfully");
@ -180,7 +170,6 @@ RCT_EXPORT_METHOD(get:(NSString *)key
rejecter:(RCTPromiseRejectBlock)reject)
{
@try {
[self handleAppUninstallation];
NSString *value = [self searchKeychainCopyMatching:key];
if (value == nil) {
NSString* errorMessage = @"{\"message\":\"key does not present\"}";
@ -214,7 +203,7 @@ RCT_EXPORT_METHOD(remove:(NSString *)key
}
}
CFStringRef accessibleValue(NSDictionary *options)
CFStringRef accessibleVal(NSDictionary *options)
{
if (options && options[@"accessible"] != nil) {
NSDictionary *keyMap = @{

View File

@ -1,22 +0,0 @@
Pod::Spec.new do |s|
s.name = "RNSecureKeyStore"
s.version = "1.0.0"
s.summary = "A package for secure storage on android and ios"
s.description = "A package for secure storage on android and ios. Stores using the keystore on Android devices, and the keychain on iOS devices."
s.homepage = "https://github.com/pradeep1991singh/react-native-secure-key-store#readme"
s.license = "MIT"
# s.license = { :type => "MIT", :file => "FILE_LICENSE" }
s.author = { "author" => "pradeep1991singh" }
s.platform = :ios, "7.0"
s.source = { :git => "https://github.com/pradeep1991singh/react-native-secure-key-store", :tag => "master" }
s.source_files = "**/*.{h,m}"
s.requires_arc = true
s.dependency "React"
#s.dependency "others"
end

View File

@ -1,11 +1,15 @@
{
"name": "react-native-secure-key-store",
"version": "2.0.4",
"version": "2.0.10",
"description": "React Native Library for securely storing keys to iOS and Android devices in KeyChain and KeyStore respectively.",
"main": "index.js",
"publishConfig": {
"registry": "https://registry.npmjs.org"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"types": "index.d.ts",
"keywords": [
"react-native",
"ios",

View File

@ -0,0 +1,24 @@
require "json"
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
Pod::Spec.new do |s|
s.name = package['name']
s.version = package['version']
s.summary = package['description']
s.description = package['description']
s.homepage = package['homepage']
s.license = package['license']
s.authors = package['author']
s.platform = :ios, "7.0"
s.source = { :git => "https://github.com/pradeep1991singh/react-native-secure-key-store", :tag => "master" }
s.source_files = "ios/**/*.{h,m}"
s.requires_arc = true
s.dependency "React-Core"
#s.dependency "others"
end