Skip to content

Commit

Permalink
fix: cipher on android (#399)
Browse files Browse the repository at this point in the history
  • Loading branch information
boorad authored Aug 11, 2024
1 parent 233ac94 commit f8161c0
Show file tree
Hide file tree
Showing 18 changed files with 332 additions and 31 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/build-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Clear up some disk space
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf "/usr/local/share/boost"
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
- name: Setup JDK
uses: actions/setup-java@v4
with:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,6 @@ lint/tmp/

# Release
.npmrc

example0/
tsconfig.tsbuildinfo
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ android {
}

defaultConfig {
minSdkVersion safeExtGet('minSdkVersion', 23)
minSdkVersion safeExtGet('minSdkVersion', 28)
targetSdkVersion safeExtGet('targetSdkVersion', 31)
versionCode 1
versionName "1.0"
Expand Down
2 changes: 1 addition & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
QuickCrypto_compileSdkVersion=31
QuickCrypto_targetSdkVersion=31
QuickCrypto_ndkversion=21.4.7075529
QuickCrypto_minSdkVersion=23
QuickCrypto_minSdkVersion=28

android.useAndroidX=true
Binary file added bun.lockb
Binary file not shown.
6 changes: 5 additions & 1 deletion cpp/Cipher/MGLPublicCipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ std::optional<jsi::Value> MGLPublicCipher::Cipher(jsi::Runtime& runtime,
return {};
}

if (EVP_PKEY_cipher_init(ctx.get()) <= 0) {
int init_ret = EVP_PKEY_cipher_init(ctx.get());
if (init_ret <= 0) {
if (init_ret == -2) {
throw std::runtime_error("operation is not supported by the public key algorithm");
}
return {};
}

Expand Down
2 changes: 1 addition & 1 deletion cpp/Cipher/MGLPublicCipherInstaller.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ FieldDefinition getPublicCipherFieldDefinition(
runtime, pkey, padding, digest, arguments[offset + 3], buf);

if (!out.has_value()) {
throw jsi::JSError(runtime, "Failed to decrypt");
throw jsi::JSError(runtime, "Failed Cipher Operation - " + name);
}

return out.value().getObject(runtime);
Expand Down
13 changes: 8 additions & 5 deletions cpp/MGLQuickCryptoHostObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,26 +63,29 @@ MGLQuickCryptoHostObject::MGLQuickCryptoHostObject(
// publicEncrypt
this->fields.push_back(
getPublicCipherFieldDefinition<MGLPublicCipher::kPublic,
EVP_PKEY_encrypt_init, EVP_PKEY_encrypt>(
EVP_PKEY_encrypt_init,
EVP_PKEY_encrypt>(
"publicEncrypt", jsCallInvoker, workerQueue));

// privateDecrypt
this->fields.push_back(
getPublicCipherFieldDefinition<MGLPublicCipher::kPrivate,
EVP_PKEY_decrypt_init, EVP_PKEY_decrypt>(
EVP_PKEY_decrypt_init,
EVP_PKEY_decrypt>(
"privateDecrypt", jsCallInvoker, workerQueue));

// privateEncrypt
this->fields.push_back(
getPublicCipherFieldDefinition<MGLPublicCipher::kPrivate,
EVP_PKEY_sign_init, EVP_PKEY_sign>(
EVP_PKEY_sign_init,
EVP_PKEY_sign>(
"privateEncrypt", jsCallInvoker, workerQueue));

// publicDecrypt
this->fields.push_back(
getPublicCipherFieldDefinition<MGLPublicCipher::kPublic,
EVP_PKEY_verify_recover_init,
EVP_PKEY_verify_recover>(
EVP_PKEY_verify_recover_init,
EVP_PKEY_verify_recover>(
"publicDecrypt", jsCallInvoker, workerQueue));

// generateKeyPair
Expand Down
4 changes: 2 additions & 2 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
buildscript {
ext {
buildToolsVersion = "34.0.0"
minSdkVersion = 23
minSdkVersion = 28
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "25.1.8937393"
Expand All @@ -13,7 +13,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.3.1")
classpath('com.android.tools.build:gradle:8.3.1')
classpath("com.facebook.react:react-native-gradle-plugin")
}
}
1 change: 1 addition & 0 deletions example/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#Fri Aug 09 17:48:30 EDT 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
Expand Down
1 change: 1 addition & 0 deletions example/babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const pak = require('../package.json');
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
['@babel/plugin-transform-class-static-block'],
[
'module-resolver',
{
Expand Down
Binary file added example/bun.lockb
Binary file not shown.
17 changes: 9 additions & 8 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,12 @@ PODS:
- react-native-quick-base64 (2.1.2):
- RCT-Folly (= 2021.07.22.00)
- React-Core
- react-native-quick-crypto (0.7.1):
- react-native-quick-crypto (0.7.2):
- OpenSSL-Universal
- RCT-Folly (= 2021.07.22.00)
- React
- React-Core
- react-native-safe-area-context (4.7.4):
- react-native-safe-area-context (4.10.8):
- React-Core
- React-NativeModulesApple (0.72.7):
- hermes-engine
Expand Down Expand Up @@ -443,9 +443,10 @@ PODS:
- RNCCheckbox (0.5.17):
- BEMCheckBox (~> 1.4)
- React-Core
- RNScreens (3.27.0):
- RNScreens (3.34.0):
- RCT-Folly (= 2021.07.22.00)
- React-Core
- React-RCTImage
- SocketRocket (0.6.1)
- Yoga (1.14.0)

Expand Down Expand Up @@ -602,11 +603,11 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
BEMCheckBox: 5ba6e37ade3d3657b36caecc35c8b75c6c2b1a4e
boost: 57d2868c099736d80fcd648bf211b4431e51a558
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
FBLazyVector: 5fbbff1d7734827299274638deb8ba3024f6c597
FBReactNativeSpec: 638095fe8a01506634d77b260ef8a322019ac671
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
glog: fdfdfe5479092de0c4bdbebedd9056951f092c4f
hermes-engine: 9180d43df05c1ed658a87cc733dc3044cf90c00a
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
OpenSSL-Universal: 6e1ae0555546e604dbc632a2b9a24a9c46c41ef6
Expand All @@ -627,8 +628,8 @@ SPEC CHECKSUMS:
React-logger: 8edc785c47c8686c7962199a307015e2ce9a0e4f
react-native-fast-encoder: 6f59e9b08e2bc5a8bf1f36e1630cdcfd66dd18af
react-native-quick-base64: 61228d753294ae643294a75fece8e0e80b7558a6
react-native-quick-crypto: 2f44f5d04eef5d925f7a1c24074d711b4f3c99d1
react-native-safe-area-context: 2cd91d532de12acdb0a9cbc8d43ac72a8e4c897c
react-native-quick-crypto: bb6d9b08f7f4a86588369cd0421adcf5da1d992a
react-native-safe-area-context: b7daa1a8df36095a032dff095a1ea8963cb48371
React-NativeModulesApple: b6868ee904013a7923128892ee4a032498a1024a
React-perflogger: 31ea61077185eb1428baf60c0db6e2886f141a5a
React-RCTActionSheet: 392090a3abc8992eb269ef0eaa561750588fc39d
Expand All @@ -647,7 +648,7 @@ SPEC CHECKSUMS:
React-utils: 56838edeaaf651220d1e53cd0b8934fb8ce68415
ReactCommon: 5f704096ccf7733b390f59043b6fa9cc180ee4f6
RNCCheckbox: a3ca9978cb0846b981d28da4e9914bd437403d77
RNScreens: 3c2d122f5e08c192e254c510b212306da97d2581
RNScreens: 80369e822c4f123c3f076c9ea4141991c17770f9
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5

Expand Down
5 changes: 3 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"@react-navigation/native-stack": "^6.9.12",
"buffer": "^6.0.3",
"chai": "^5.0.0",
"eslint": "^8.4.1",
"events": "^3.3.0",
"mocha": "^10.2.0",
"react": "18.2.0",
Expand All @@ -35,9 +34,10 @@
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/plugin-transform-class-static-block": "^7.24.7",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native/gradle-plugin": "^0.75.0-main",
"@react-native/gradle-plugin": "0.74.87",
"@react-native/metro-config": "^0.73.2",
"@tsconfig/react-native": "^2.0.2",
"@types/chai": "^4.3.4",
Expand All @@ -48,6 +48,7 @@
"@types/react-test-renderer": "^18.0.0",
"@types/readable-stream": "^4.0.11",
"babel-plugin-module-resolver": "^5.0.0",
"eslint": "^8.4.1",
"metro-react-native-babel-preset": "0.76.8",
"prettier": "^2.4.1"
},
Expand Down
1 change: 1 addition & 0 deletions example/src/hooks/useTestList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import '../testing/Tests/HmacTests/HmacTests';
import '../testing/Tests/HashTests/HashTests';
import '../testing/Tests/CipherTests/CipherTestFirst';
import '../testing/Tests/CipherTests/CipherTestSecond';
import '../testing/Tests/CipherTests/test398';
import '../testing/Tests/CipherTests/PublicCipherTests';
import '../testing/Tests/CipherTests/generateKey';
import '../testing/Tests/CipherTests/GenerateKeyPairTests';
Expand Down
104 changes: 104 additions & 0 deletions example/src/testing/Tests/CipherTests/test398.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import type { BinaryLikeNode } from './../../../../../src/Utils';
import { Buffer } from 'buffer';
// import { Buffer } from '@craftzdog/react-native-buffer';
import crypto from 'react-native-quick-crypto';
import { describe, it } from '../../MochaRNAdapter';
import { expect } from 'chai';

type EncryptRequest = {
payload: string;
publicKey: ArrayBuffer;
};
type EncryptResponse = {
KEY: string;
IV: string;
PAYLOAD: string;
secretKey: BinaryLikeNode;
};

const algo = 'aes-128-gcm';

const encrypt = ({ payload, publicKey }: EncryptRequest): EncryptResponse => {
const secretKey = crypto.randomBytes(16);
const iv = crypto.randomBytes(16);

const cipher = crypto.createCipheriv(algo, secretKey, iv);

const encryptedPayload = Buffer.concat([
cipher.update(payload, 'utf8'),
cipher.final(),
cipher.getAuthTag(),
]).toString('base64');

const encryptedSessionKey = crypto.publicEncrypt(
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
},
secretKey
);

return {
KEY: encryptedSessionKey.toString('base64'),
IV: iv.toString('base64'),
PAYLOAD: encryptedPayload,
secretKey,
};
};

const decrypt = ({
response,
secretKey,
}: {
response: EncryptResponse;
secretKey: BinaryLikeNode;
}) => {
const { IV, PAYLOAD } = response;

const decipher = crypto.createDecipheriv(
algo,
secretKey,
Buffer.from(IV, 'base64')
);

const encryptedPayload = Buffer.from(PAYLOAD, 'base64');
let decrypted = decipher.update(
Buffer.from(encryptedPayload.subarray(0, encryptedPayload.length - 16))
);
decrypted = Buffer.concat([decrypted, decipher.final()]);

return JSON.parse(decrypted.toString('utf8'));
};

const getPublicKeyInPEMFormat = (key: string): ArrayBuffer => {
return crypto
.createPublicKey({
key: Buffer.from(key, 'base64'),
format: 'der',
type: 'spki',
})
.export({
type: 'spki',
format: 'pem',
});
};

describe('test398', () => {
it('test398', () => {
const publicKeySpkiBase64 =
'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENlFpbMBNfCY6Lhj9A/clefyxJVIXGJ0y6CcZ/cbbyyebvN6T0aNPvpQyFdUwRtYvFHlYbqIZOM8AoqdPcnSMIA==';

const publicKey = getPublicKeyInPEMFormat(publicKeySpkiBase64);
console.log('\n' + publicKey);
const encrypted = encrypt({
payload: JSON.stringify({ a: 1 }),
publicKey,
});
console.log({ encrypted });
const { response: decrypted } = decrypt({
response: encrypted,
secretKey: encrypted.secretKey,
});
expect(decrypted).to.equal({ a: 1 });
});
});
Loading

0 comments on commit f8161c0

Please sign in to comment.