Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: rewrite to C++ with JSI #122

Merged
merged 5 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ module.exports = {
rules: {
'jsx-quotes': ['error', 'prefer-single'],
'react/jsx-filename-extension': 0,
'@typescript-eslint/no-shadow': 0,
},
};
58 changes: 51 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,66 @@
#
.DS_Store

# XDE
.expo/

# VSCode
.vscode/
jsconfig.json

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

# Android/IJ
#
.classpath
.cxx
.gradle
.idea
.project
.settings
local.properties
android.iml

# Cocoapods
#
example/ios/Pods

# node.js
#
node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log

# generated by bob
lib/
# BUCK
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore

# iOS
project.xcworkspace
xcuserdata
# Expo
.expo/*

# Android
android/.gradle
# generated by bob
lib/

# tests
.nyc_output
5 changes: 5 additions & 0 deletions CHANGELOGS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelogs

# Unreleased
* Rewrite to C++ with JSI.
* Removed extra Expo dependencies.
* Removed `asyncPkceChallenge` support.

# 4.0.1 (2022-07-12)
* Fixed missing `macos` files.

Expand Down
31 changes: 11 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,25 @@
Proof Key for Code Exchange (PKCE) challenge generator for React Native.

## API Compatibility
Method |iOS |Android |Web |Windows |macOS |Expo
:--------------------|:------------------|:------------------|:------------------|:------------------|:------------------|:------------------
`asyncPkceChallenge` |:white_check_mark: |:white_check_mark: |:white_check_mark: |:x: |:white_check_mark: |:white_check_mark:
`pkceChallenge` |:white_check_mark: |:white_check_mark: |:white_check_mark: |:white_check_mark: |:white_check_mark: |:white_check_mark:
|iOS |Android |Web |Windows |macOS |Expo
|:------------------|:------------------|:------------------|:------------------|:------------------|:------------------
|:white_check_mark: |:white_check_mark: |:white_check_mark: |:white_check_mark: |:white_check_mark: |:white_check_mark:

## Under the hood
|iOS |Android |Web |Windows |macOS |Expo
|:--------------|:--------------|:------------------|:-----------|:--------------|:-----------
|arc4random_buf |arc4random_buf |crypto.randombytes |Math.random |arc4random_buf |expo-random

## Installation
```bash
yarn add react-native-pkce-challenge
npx pod-install # iOS Only
```

## Installation (Expo)
```bash
expo install react-native-pkce-challenge expo-random buffer
npx pod-install ios # iOS Only
npx pod-install macos # macOS Only
```
> :bulb: If you use Expo you might not need this package. See: https://docs.expo.dev/versions/latest/sdk/auth-session/

## Usage
### Asynchronous (Recommended)
```js
import { asyncPkceChallenge } from 'react-native-pkce-challenge';

const challenge = await asyncPkceChallenge();
```

### Synchronous
```js
import { pkceChallenge } from 'react-native-pkce-challenge';
import pkceChallenge from 'react-native-pkce-challenge';

const challenge = pkceChallenge();
```
Expand Down
23 changes: 16 additions & 7 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
# Upgrading
## From 4.X.X to Unreleased
* For `Expo` only, run `yarn remove expo-random buffer`.

Make the following changes:
```diff
- import { asyncPkceChallenge } from 'react-native-pkce-challenge';
+ import pkceChallenge from 'react-native-pkce-challenge';
```

## From 3.X.X to 4.X.X
* No actions required.

## From 2.X.X to 3.X.X
Run the following:
* `yarn remove react-native-randombytes`
* `npx pod-install`

## From 1.X.X to 2.X.X
Change:
```js
import pkceChallenge from 'react-native-pkce-challenge';
```
To:
```js
import { asyncPkceChallenge } from 'react-native-pkce-challenge';
Make the following changes:
```diff
- import pkceChallenge from 'react-native-pkce-challenge';
+ import { asyncPkceChallenge } from 'react-native-pkce-challenge';
```
29 changes: 29 additions & 0 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.9.0)

add_library(
randombytes
SHARED
../../react-native/ReactCommon/jsi/jsi/jsi.cpp
../cpp/random-bytes.cpp
../cpp/base64.cpp
./cpp-adapter.cpp
)

include_directories(
../../react-native/React
../../react-native/React/Base
../../react-native/ReactCommon/jsi
../cpp
)

set_target_properties(
randombytes PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON
)

target_link_libraries(
randombytes
android
)
68 changes: 60 additions & 8 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,21 +1,73 @@
def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
buildscript {
if (project == rootProject) {
repositories {
google()
mavenCentral()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
}
}
}

apply plugin: 'com.android.library'

android {
compileSdkVersion safeExtGet('compileSdkVersion', 26)
buildToolsVersion safeExtGet('buildToolsVersion', '26.0.2')
def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}

android {
compileSdkVersion safeExtGet('compileSdkVersion', 29)
defaultConfig {
minSdkVersion safeExtGet('minSdkVersion', 16)
targetSdkVersion safeExtGet('targetSdkVersion', 26)
targetSdkVersion safeExtGet('targetSdkVersion', 29)
versionCode 1
versionName '1.0'
versionName "1.0"

externalNativeBuild {
cmake {
cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all"
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
}
}

externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}

buildTypes {
release {
minifyEnabled false
}
}

lintOptions {
disable 'GradleCompatible'
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

repositories {
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
google()
mavenCentral()
jcenter()
}

dependencies {
implementation 'com.facebook.react:react-native:+'
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
}
13 changes: 13 additions & 0 deletions android/cpp-adapter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <jni.h>
#include "random-bytes.h"

extern "C" JNIEXPORT void JNICALL
Java_com_davidangulo_randombytes_RandomBytesModule_nativeInstall(JNIEnv *env, jobject thiz, jlong jsi)
{
auto runtime = reinterpret_cast<facebook::jsi::Runtime *>(jsi);

if (runtime)
{
randombytes::install(*runtime);
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
package com.davidangulo.randombytes;

import androidx.annotation.NonNull;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import java.security.SecureRandom;
import android.util.Base64;

@ReactModule(name = RandomBytesModule.NAME)
public class RandomBytesModule extends ReactContextBaseJavaModule {
public static final String NAME = "RandomBytes";
private native void nativeInstall(long jsiPtr, String docDir);

public RandomBytesModule(ReactApplicationContext reactContext) {
super(reactContext);
}

@NonNull
@Override
public String getName() {
return "RandomBytes";
return NAME;
}

@ReactMethod
public void randomBytes(Callback callback) {
byte[] bytes = new byte[96];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(bytes);
callback.invoke(Base64.encodeToString(bytes, Base64.NO_WRAP));
@ReactMethod(isBlockingSynchronousMethod = true)
public boolean install() {
try {
System.loadLibrary("randombytes");

ReactApplicationContext context = getReactApplicationContext();
nativeInstall(
context.getJavaScriptContextHolder().get(),
context.getFilesDir().getAbsolutePath()
);
return true;
} catch (Exception exception) {
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
package com.davidangulo.randombytes;

import androidx.annotation.NonNull;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RandomBytesPackage implements ReactPackage {
@NonNull
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();

modules.add(new RandomBytesModule(reactContext));

return modules;
}

@NonNull
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
Expand Down
Loading