Skip to content

Commit

Permalink
tests & fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
boorad committed Jun 19, 2024
1 parent 0b40eae commit d4778df
Show file tree
Hide file tree
Showing 19 changed files with 188 additions and 116 deletions.
112 changes: 69 additions & 43 deletions cpp/MGLKeys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -676,19 +676,25 @@ ManagedEVPPKey ManagedEVPPKey::GetPrivateKeyFromJs(jsi::Runtime& runtime,
return GetParsedKey(runtime, std::move(pkey), ret,
"Failed to read private key");
} else {
// CHECK(args[*offset]->IsObject() && allow_key_object);
// KeyObjectHandle* key;
// ASSIGN_OR_RETURN_UNWRAP(&key, args[*offset].As<Object>(),
// ManagedEVPPKey()); CHECK_EQ(key->Data()->GetKeyType(),
// kKeyTypePrivate);
// (*offset) += 4;
// return key->Data()->GetAsymmetricKey();
throw jsi::JSError(runtime, "KeyObject are not currently supported");
if( !(args[*offset].isObject() && allow_key_object)) {
throw jsi::JSError(runtime,
"ManagedEVPPKey::GetPrivateKeyFromJs: First argument "
"must be object (CryptoKey) and caller must pass "
"allow_key_object as true");
}
std::shared_ptr<KeyObjectHandle> handle =
std::static_pointer_cast<KeyObjectHandle>(
args[*offset].asObject(runtime).getHostObject(runtime));
CHECK_EQ(handle->Data()->GetKeyType(), kKeyTypePrivate);
(*offset) += 4;
return handle->Data()->GetAsymmetricKey();
}
}

ManagedEVPPKey ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
jsi::Runtime& runtime, const jsi::Value* args, unsigned int* offset) {
jsi::Runtime& runtime,
const jsi::Value* args,
unsigned int* offset) {
if (args[*offset].asObject(runtime).isArrayBuffer(runtime)) {
auto dataArrayBuffer =
args[(*offset)++].asObject(runtime).getArrayBuffer(runtime);
Expand Down Expand Up @@ -749,15 +755,19 @@ ManagedEVPPKey ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
return ManagedEVPPKey::GetParsedKey(runtime, std::move(pkey), ret,
"Failed to read asymmetric key");
} else {
throw jsi::JSError(
runtime, "public encrypt only supports ArrayBuffer at the moment");
// CHECK(args[*offset]->IsObject());
// KeyObjectHandle* key =
// Unwrap<KeyObjectHandle>(args[*offset].As<Object>());
// CHECK_NOT_NULL(key);
// CHECK_NE(key->Data()->GetKeyType(), kKeyTypeSecret);
// (*offset) += 4;
// return key->Data()->GetAsymmetricKey();
if( !(args[*offset].isObject()) ) {
throw jsi::JSError(runtime,
"ManagedEVPPKey::GetPublicOrPrivateKeyFromJs: First "
"argument not ArrayBuffer or object (CryptoKey)");
}
std::shared_ptr<KeyObjectHandle> handle =
std::static_pointer_cast<KeyObjectHandle>(
args[*offset].asObject(runtime).getHostObject(runtime));
// note: below check is kKeyTypeSecret in Node.js
// but kKeyTypePublic in RNQC when testing verify() on ECDSA
CHECK_EQ(handle->Data()->GetKeyType(), kKeyTypePublic);
(*offset) += 4;
return handle->Data()->GetAsymmetricKey();
}
}

Expand Down Expand Up @@ -846,6 +856,8 @@ jsi::Value KeyObjectHandle::get(
return this->InitJWK(rt);
} else if (name == "keyDetail") {
return this->GetKeyDetail(rt);
} else if (name == "getAsymmetricKeyType") {
return this->GetAsymmetricKeyType(rt);
}

return {};
Expand Down Expand Up @@ -1149,31 +1161,45 @@ jsi::Value KeyObjectHandle::GetKeyDetail(jsi::Runtime &rt) {
});
}

// Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
// const ManagedEVPPKey& key = data_->GetAsymmetricKey();
// switch (EVP_PKEY_id(key.get())) {
// case EVP_PKEY_RSA:
// return env()->crypto_rsa_string();
// case EVP_PKEY_RSA_PSS:
// return env()->crypto_rsa_pss_string();
// case EVP_PKEY_DSA:
// return env()->crypto_dsa_string();
// case EVP_PKEY_DH:
// return env()->crypto_dh_string();
// case EVP_PKEY_EC:
// return env()->crypto_ec_string();
// case EVP_PKEY_ED25519:
// return env()->crypto_ed25519_string();
// case EVP_PKEY_ED448:
// return env()->crypto_ed448_string();
// case EVP_PKEY_X25519:
// return env()->crypto_x25519_string();
// case EVP_PKEY_X448:
// return env()->crypto_x448_string();
// default:
// return Undefined(env()->isolate());
// }
//}
jsi::Value KeyObjectHandle::GetAsymmetricKeyType(jsi::Runtime &rt) const {
return HOSTFN("getAsymmetricKeyType", 0) {
const ManagedEVPPKey& key = this->data_->GetAsymmetricKey();
std::string ret;
switch (EVP_PKEY_id(key.get())) {
case EVP_PKEY_RSA:
ret = "rss";
break;
case EVP_PKEY_RSA_PSS:
ret = "rsa_pss";
break;
case EVP_PKEY_DSA:
ret = "dsa";
break;
case EVP_PKEY_DH:
ret = "dh";
break;
case EVP_PKEY_EC:
ret = "ec";
break;
case EVP_PKEY_ED25519:
ret = "ed25519";
break;
case EVP_PKEY_ED448:
ret = "ed448";
break;
case EVP_PKEY_X25519:
ret = "x25519";
break;
case EVP_PKEY_X448:
ret = "x448";
break;
default:
throw jsi::JSError(rt, "unknown KeyType in GetAsymmetricKeyType");
}
return jsi::String::createFromUtf8(rt, ret);
});
}

//
// void KeyObjectHandle::GetAsymmetricKeyType(
// const
Expand Down
3 changes: 2 additions & 1 deletion cpp/MGLKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,11 @@ class JSI_EXPORT KeyObjectHandle: public jsi::HostObject {
jsi::Runtime& rt,
const PrivateKeyEncodingConfig& config) const;
jsi::Value ExportSecretKey(jsi::Runtime& rt) const;
jsi::Value GetKeyDetail(jsi::Runtime &rt);
jsi::Value GetAsymmetricKeyType(jsi::Runtime &rt) const;
jsi::Value Init(jsi::Runtime &rt);
jsi::Value InitECRaw(jsi::Runtime &rt);
jsi::Value InitJWK(jsi::Runtime &rt);
jsi::Value GetKeyDetail(jsi::Runtime &rt);

private:
std::shared_ptr<KeyObjectData> data_;
Expand Down
34 changes: 14 additions & 20 deletions cpp/Sig/MGLSignHostObjects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,18 +494,6 @@ void SignBase::InstallMethods(mode mode) {
}
}

SubtleSignVerify::SubtleSignVerify(std::shared_ptr<react::CallInvoker> jsCallInvoker,
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
: MGLSmartHostObject(jsCallInvoker, workerQueue)
{
this->fields.push_back(buildPair(
"signVerify", JSIF([=]) {
auto params = this->GetParamsFromJS(runtime, arguments);
ByteSource out = this->DoSignVerify(runtime, params);
return this->EncodeOutput(runtime, params, out);
}));
};

// SignConfiguration::SignConfiguration(SignConfiguration&& other) noexcept
//: job_mode(other.job_mode),
// mode(other.mode),
Expand Down Expand Up @@ -560,6 +548,10 @@ SignConfiguration SubtleSignVerify::GetParamsFromJS(jsi::Runtime &rt,
offset = 5;

// data
if (!args[offset].isObject() || !args[offset].asObject(rt).isArrayBuffer(rt)) {
throw jsi::JSError(rt, "data is not an array buffer");
return params;
}
ByteSource data = ByteSource::FromStringOrBuffer(rt, args[offset]);
if (data.size() > INT_MAX) {
throw jsi::JSError(rt, "data is too big (> int32)");
Expand Down Expand Up @@ -628,9 +620,11 @@ SignConfiguration SubtleSignVerify::GetParamsFromJS(jsi::Runtime &rt,
return params;
}

ByteSource SubtleSignVerify::DoSignVerify(jsi::Runtime &rt,
const SignConfiguration &params) {
ByteSource out;
// Subtle Sign/Verify

void SubtleSignVerify::DoSignVerify(jsi::Runtime &rt,
const SignConfiguration &params,
ByteSource &out) {

EVPMDPointer context(EVP_MD_CTX_new());
EVP_PKEY_CTX* ctx = nullptr;
Expand Down Expand Up @@ -733,19 +727,19 @@ ByteSource SubtleSignVerify::DoSignVerify(jsi::Runtime &rt,
}
}

return out;
// return out;
}

jsi::Value SubtleSignVerify::EncodeOutput(jsi::Runtime &rt,
const SignConfiguration &params,
ByteSource &out) {
JSVariant result;
ByteSource &output) {
jsi::Value result;
switch (params.mode) {
case SignConfiguration::kSign:
result = JSVariant(std::move(out));
result = toJSI(rt, std::move(output));
break;
case SignConfiguration::kVerify:
result = JSVariant(out.data<char>()[0] == 1);
result = jsi::Value(output.data<char>()[0] == 1);
break;
default:
throw jsi::JSError(rt, "unreachable code in SubtleSignVerify::EncodeOutput");
Expand Down
14 changes: 3 additions & 11 deletions cpp/Sig/MGLSignHostObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,11 @@ struct SignConfiguration final { // : public MemoryRetainer
// SET_SELF_SIZE(SignConfiguration)
};

class SubtleSignVerify : public MGLSmartHostObject {
class SubtleSignVerify {
public:
SubtleSignVerify(std::shared_ptr<react::CallInvoker> jsCallInvoker,
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);

SignConfiguration GetParamsFromJS(jsi::Runtime &rt, const jsi::Value *args);

ByteSource SubtleSignVerify::DoSignVerify(jsi::Runtime &rt,
const SignConfiguration &params);

jsi::Value SubtleSignVerify::EncodeOutput(jsi::Runtime &rt,
const SignConfiguration &params,
ByteSource &out);
void DoSignVerify(jsi::Runtime &rt, const SignConfiguration &params, ByteSource &out);
jsi::Value EncodeOutput(jsi::Runtime &rt,const SignConfiguration &params, ByteSource &out);
};

class MGLSignHostObject : public SignBase {
Expand Down
12 changes: 11 additions & 1 deletion cpp/webcrypto/MGLWebCrypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
#include <memory>
#include <utility>
#include "MGLKeys.h"
#include <MGLSignHostObjects.h>

#ifdef ANDROID
#include "Utils/MGLUtils.h"
#include "JSIUtils/MGLJSIMacros.h"
#include "webcrypto/crypto_ec.h"
#include "Utils/MGLUtils.h"
#else
#include "MGLUtils.h"
#include "MGLJSIMacros.h"
Expand Down Expand Up @@ -51,10 +52,19 @@ jsi::Value createWebCryptoObject(jsi::Runtime &rt) {
return toJSI(rt, std::move(out));
});

auto signVerify = HOSTFN("signVerify", 4) {
auto ssv = SubtleSignVerify();
auto params = ssv.GetParamsFromJS(rt, args);
ByteSource out;
ssv.DoSignVerify(rt, params, out);
return ssv.EncodeOutput(rt, params, out);
});

obj.setProperty(rt,
"createKeyObjectHandle",
std::move(createKeyObjectHandle));
obj.setProperty(rt, "ecExportKey", std::move(ecExportKey));
obj.setProperty(rt, "signVerify", std::move(signVerify));
return obj;
};

Expand Down
11 changes: 9 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,13 @@ PODS:
- React-jsinspector (0.72.7)
- React-logger (0.72.7):
- glog
- react-native-fast-encoder (0.1.12):
- RCT-Folly (= 2021.07.22.00)
- React-Core
- react-native-quick-base64 (2.1.2):
- RCT-Folly (= 2021.07.22.00)
- React-Core
- react-native-quick-crypto (0.7.0-rc.6):
- react-native-quick-crypto (0.7.0-rc.9):
- OpenSSL-Universal
- RCT-Folly (= 2021.07.22.00)
- React
Expand Down Expand Up @@ -470,6 +473,7 @@ DEPENDENCIES:
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- react-native-fast-encoder (from `../node_modules/react-native-fast-encoder`)
- react-native-quick-base64 (from `../node_modules/react-native-quick-base64`)
- react-native-quick-crypto (from `../..`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
Expand Down Expand Up @@ -546,6 +550,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
React-logger:
:path: "../node_modules/react-native/ReactCommon/logger"
react-native-fast-encoder:
:path: "../node_modules/react-native-fast-encoder"
react-native-quick-base64:
:path: "../node_modules/react-native-quick-base64"
react-native-quick-crypto:
Expand Down Expand Up @@ -619,8 +625,9 @@ SPEC CHECKSUMS:
React-jsiexecutor: c49502e5d02112247ee4526bc3ccfc891ae3eb9b
React-jsinspector: 8baadae51f01d867c3921213a25ab78ab4fbcd91
React-logger: 8edc785c47c8686c7962199a307015e2ce9a0e4f
react-native-fast-encoder: 6f59e9b08e2bc5a8bf1f36e1630cdcfd66dd18af
react-native-quick-base64: 61228d753294ae643294a75fece8e0e80b7558a6
react-native-quick-crypto: 0f1c9ae20bc06e10f0349887a9e3767ff683c5ac
react-native-quick-crypto: 8e4521904e2b9da9454bcd825e9c198a1efb3f29
react-native-safe-area-context: 2cd91d532de12acdb0a9cbc8d43ac72a8e4c897c
React-NativeModulesApple: b6868ee904013a7923128892ee4a032498a1024a
React-perflogger: 31ea61077185eb1428baf60c0db6e2886f141a5a
Expand Down
2 changes: 2 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"mocha": "^10.2.0",
"react": "18.2.0",
"react-native": "0.72.7",
"react-native-fast-encoder": "^0.1.12",
"react-native-quick-base64": "^2.1.2",
"react-native-safe-area-context": "^4.5.0",
"react-native-screens": "^3.20.0",
Expand All @@ -43,6 +44,7 @@
"@types/jest": "^29.2.1",
"@types/mocha": "^10.0.1",
"@types/react": "^18.0.24",
"@types/react-native": "^0.72.7",
"@types/react-test-renderer": "^18.0.0",
"@types/readable-stream": "^4.0.11",
"babel-plugin-module-resolver": "^5.0.0",
Expand Down
2 changes: 1 addition & 1 deletion example/src/components/TestItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const TestItem: React.FC<TestItemProps> = ({
const styles = StyleSheet.create({
container: {
width: '100%',
paddingVertical: 5,
paddingVertical: 2,
flexDirection: 'row',
alignContent: 'center',
alignItems: 'center',
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 @@ -19,6 +19,7 @@ import '../testing/Tests/webcryptoTests/deriveBits';
import '../testing/Tests/webcryptoTests/digest';
import '../testing/Tests/webcryptoTests/generateKey';
import '../testing/Tests/webcryptoTests/import_export';
import '../testing/Tests/webcryptoTests/sign_verify';

export const useTestList = (): [
Suites,
Expand Down
9 changes: 1 addition & 8 deletions example/src/testing/Tests/webcryptoTests/generateKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import crypto from 'react-native-quick-crypto';
import { assertThrowsAsync } from '../util';
import type {
AnyAlgorithm,
CryptoKey,
CryptoKeyPair,
KeyUsage,
NamedCurve,
Expand Down Expand Up @@ -427,11 +426,6 @@ describe('subtle - generateKey', () => {
}
*/

type CryptoKeysInPair = {
publicKey: CryptoKey;
privateKey: CryptoKey;
};

// Test EC Key Generation
{
async function testECKeyGen(
Expand All @@ -454,8 +448,7 @@ describe('subtle - generateKey', () => {
true,
usages
);
const { publicKey, privateKey }: CryptoKeysInPair =
pair as CryptoKeyPair;
const { publicKey, privateKey } = pair as CryptoKeyPair;

expect(publicKey).is.not.undefined;
expect(privateKey).is.not.undefined;
Expand Down
Loading

0 comments on commit d4778df

Please sign in to comment.