Skip to content

Commit 131c9fb

Browse files
committed
fix: moar tests, android build
1 parent 9bfd71e commit 131c9fb

File tree

10 files changed

+173
-25
lines changed

10 files changed

+173
-25
lines changed

bun.lock

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,15 @@
9191
"del-cli": "6.0.0",
9292
"expo": "^47.0.0",
9393
"jest": "29.7.0",
94-
"nitro-codegen": "0.26.2",
94+
"nitro-codegen": "0.26.4",
9595
"react-native-builder-bob": "0.39.1",
96-
"react-native-nitro-modules": "0.26.2",
96+
"react-native-nitro-modules": "0.26.4",
9797
},
9898
"peerDependencies": {
9999
"expo": ">=47.0.0",
100100
"react": "*",
101101
"react-native": "*",
102-
"react-native-nitro-modules": ">=0.26.2",
102+
"react-native-nitro-modules": ">=0.26.4",
103103
},
104104
"optionalPeers": [
105105
"expo",
@@ -1956,7 +1956,7 @@
19561956

19571957
"nice-try": ["[email protected]", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="],
19581958

1959-
"nitro-codegen": ["[email protected].2", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.26.2", "ts-morph": "^25.0.0", "yargs": "^17.7.2", "zod": "^3.23.8" }, "bin": { "nitro-codegen": "lib/index.js" } }, "sha512-Z66PE0kzwrTdvyUMsq0eCv6IcEsv+tpkZovGcIat/UVJrcbbBNaScKuFRL07Qoh7idm4mErJiei6IRewJUDghA=="],
1959+
"nitro-codegen": ["[email protected].4", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.26.4", "ts-morph": "^25.0.0", "yargs": "^17.7.2", "zod": "^4.0.5" }, "bin": { "nitro-codegen": "lib/index.js" } }, "sha512-qTOvyfE6+kz0wuqPpRlKc6F6ZNOI3elK7ltOTvxMZSG3Y8tt43UrV5xkp4XgL9Jc1P90iBLU6mDYRiNqoNA2+g=="],
19601960

19611961
"nocache": ["[email protected]", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="],
19621962

@@ -2188,7 +2188,7 @@
21882188

21892189
"react-native-builder-bob": ["[email protected]", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-transform-strict-mode": "^7.24.7", "@babel/preset-env": "^7.25.2", "@babel/preset-flow": "^7.24.7", "@babel/preset-react": "^7.24.7", "@babel/preset-typescript": "^7.24.7", "babel-plugin-module-resolver": "^5.0.2", "browserslist": "^4.20.4", "cross-spawn": "^7.0.3", "dedent": "^0.7.0", "del": "^6.1.1", "escape-string-regexp": "^4.0.0", "fs-extra": "^10.1.0", "glob": "^8.0.3", "is-git-dirty": "^2.0.1", "json5": "^2.2.1", "kleur": "^4.1.4", "metro-config": "^0.80.9", "prompts": "^2.4.2", "which": "^2.0.2", "yargs": "^17.5.1" }, "bin": { "bob": "bin/bob" } }, "sha512-nEG9FB5a2Rxw0251dnlM9QtqvuM2os8avRhYDWDdvsZOnQJhQI4fGV5wF5FypAqHNWPQUNXmvhPUFrPSwiPnAQ=="],
21902190

2191-
"react-native-nitro-modules": ["[email protected].2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-PvTUOryU/J1RDsPh1IvmAEDkYVVL32wCIYxkg6HsKgq+Dl+C8lth/MtW7cRZ+fJ0qW21NILbhBdhSXFzBx51fA=="],
2191+
"react-native-nitro-modules": ["[email protected].4", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-sCZ0U+FY6JM73HaZYyc4kSRV7JQZXGfbimpYJzaAaZFQMGpJFkD5c3Jt66j1v83wN/m6D/SM9yyx+dN6XTfGAg=="],
21922192

21932193
"react-native-quick-base64": ["[email protected]", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-r7/BRsRl8QKEhS0JsHW6QX9+8LrC6NNWlwNnBnZ69h2kbcfABYsUILT71obrs9fqElEIMzuYSI5aHID955akyQ=="],
21942194

@@ -2666,7 +2666,7 @@
26662666

26672667
"yoctocolors-cjs": ["[email protected]", "", {}, "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA=="],
26682668

2669-
"zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
2669+
"zod": ["zod@4.1.3", "", {}, "sha512-1neef4bMce1hNTrxvHVKxWjKfGDn0oAli3Wy1Uwb7TRO1+wEwoZUZNP1NXIEESybOBiFnBOhI6a4m6tCLE8dog=="],
26702670

26712671
"@babel/core/semver": ["[email protected]", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
26722672

@@ -3500,8 +3500,6 @@
35003500

35013501
"react-native-builder-bob/yargs": ["[email protected]", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
35023502

3503-
"react-native-quick-crypto-example/react-native-nitro-modules": ["[email protected]", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-sCZ0U+FY6JM73HaZYyc4kSRV7JQZXGfbimpYJzaAaZFQMGpJFkD5c3Jt66j1v83wN/m6D/SM9yyx+dN6XTfGAg=="],
3504-
35053503
"read-package-up/type-fest": ["[email protected]", "", {}, "sha512-bRkIGlXsnGBRBQRAY56UXBm//9qH4bmJfFvq83gSz41N282df+fjy8ofcEgc1sM8geNt5cl6mC2g9Fht1cs8Aw=="],
35063504

35073505
"read-pkg/parse-json": ["[email protected]", "", { "dependencies": { "@babel/code-frame": "^7.22.13", "index-to-position": "^0.1.2", "type-fest": "^4.7.1" } }, "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA=="],
6.22 KB
Loading

docs/test_suite_results_ios.png

-638 Bytes
Loading

example/android/app/src/main/java/com/quickcryptoexample/MainApplication.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import android.app.Application
44
import com.facebook.react.PackageList
55
import com.facebook.react.ReactApplication
66
import com.facebook.react.ReactHost
7-
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
87
import com.facebook.react.ReactNativeHost
98
import com.facebook.react.ReactPackage
9+
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
1010
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
1111
import com.facebook.react.defaults.DefaultReactNativeHost
12+
import com.facebook.react.soloader.OpenSourceMergedSoMapping
13+
import com.facebook.soloader.SoLoader
1214

1315
class MainApplication : Application(), ReactApplication {
1416

@@ -33,6 +35,10 @@ class MainApplication : Application(), ReactApplication {
3335

3436
override fun onCreate() {
3537
super.onCreate()
36-
loadReactNative(this)
38+
SoLoader.init(this, OpenSourceMergedSoMapping)
39+
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
40+
// If you opted-in for the New Architecture, we load the native entry point for this app.
41+
load()
42+
}
3743
}
3844
}

example/src/hooks/useTestsList.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { TestsContext } from '../tests/util';
55
import '../tests/cipher/cipher_tests';
66
import '../tests/cipher/chacha_tests';
77
import '../tests/cipher/xsalsa20_tests';
8-
// import '../tests/ed25519/ed25519_tests';
8+
import '../tests/ed25519/ed25519_tests';
99
import '../tests/ed25519/x25519_tests';
1010
import '../tests/hash/hash_tests';
1111
import '../tests/hmac/hmac_tests';

example/src/tests/ed25519/x25519_tests.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,130 @@ test(SUITE, 'x25519 - shared secret', () => {
2929
});
3030
void expect(Buffer.isBuffer(sharedSecret)).to.be.true;
3131
});
32+
33+
test(SUITE, 'x25519 - shared secret symmetry', () => {
34+
// Generate key pairs
35+
const alice = crypto.generateKeyPairSync('x25519', {});
36+
const bob = crypto.generateKeyPairSync('x25519', {});
37+
38+
// Create KeyObject instances
39+
const alicePrivate = KeyObject.createKeyObject(
40+
'private',
41+
alice.privateKey as ArrayBuffer,
42+
);
43+
const alicePublic = KeyObject.createKeyObject(
44+
'public',
45+
alice.publicKey as ArrayBuffer,
46+
);
47+
const bobPrivate = KeyObject.createKeyObject(
48+
'private',
49+
bob.privateKey as ArrayBuffer,
50+
);
51+
const bobPublic = KeyObject.createKeyObject(
52+
'public',
53+
bob.publicKey as ArrayBuffer,
54+
);
55+
56+
// Compute shared secrets from both sides
57+
const sharedSecretAlice = crypto.diffieHellman({
58+
privateKey: alicePrivate,
59+
publicKey: bobPublic,
60+
}) as Buffer;
61+
62+
const sharedSecretBob = crypto.diffieHellman({
63+
privateKey: bobPrivate,
64+
publicKey: alicePublic,
65+
}) as Buffer;
66+
67+
// Verify both sides compute the same shared secret
68+
void expect(Buffer.isBuffer(sharedSecretAlice)).to.be.true;
69+
void expect(Buffer.isBuffer(sharedSecretBob)).to.be.true;
70+
void expect(sharedSecretAlice.equals(sharedSecretBob)).to.be.true;
71+
});
72+
73+
test(SUITE, 'x25519 - shared secret properties', () => {
74+
const alice = crypto.generateKeyPairSync('x25519', {});
75+
const bob = crypto.generateKeyPairSync('x25519', {});
76+
77+
const alicePrivate = KeyObject.createKeyObject(
78+
'private',
79+
alice.privateKey as ArrayBuffer,
80+
);
81+
const bobPublic = KeyObject.createKeyObject(
82+
'public',
83+
bob.publicKey as ArrayBuffer,
84+
);
85+
86+
const sharedSecret = crypto.diffieHellman({
87+
privateKey: alicePrivate,
88+
publicKey: bobPublic,
89+
}) as Buffer;
90+
91+
// X25519 shared secrets should be exactly 32 bytes
92+
void expect(sharedSecret.length).to.equal(32);
93+
94+
// Should not be all zeros (extremely unlikely with proper implementation)
95+
const allZeros = Buffer.alloc(32, 0);
96+
void expect(sharedSecret.equals(allZeros)).to.be.false;
97+
98+
// Should be deterministic - same keys produce same secret
99+
const sharedSecret2 = crypto.diffieHellman({
100+
privateKey: alicePrivate,
101+
publicKey: bobPublic,
102+
}) as Buffer;
103+
void expect(sharedSecret.equals(sharedSecret2)).to.be.true;
104+
});
105+
106+
test(SUITE, 'x25519 - different key pairs produce different secrets', () => {
107+
const alice = crypto.generateKeyPairSync('x25519', {});
108+
const bob = crypto.generateKeyPairSync('x25519', {});
109+
const charlie = crypto.generateKeyPairSync('x25519', {});
110+
111+
const alicePrivate = KeyObject.createKeyObject(
112+
'private',
113+
alice.privateKey as ArrayBuffer,
114+
);
115+
const bobPublic = KeyObject.createKeyObject(
116+
'public',
117+
bob.publicKey as ArrayBuffer,
118+
);
119+
const charliePublic = KeyObject.createKeyObject(
120+
'public',
121+
charlie.publicKey as ArrayBuffer,
122+
);
123+
124+
const secretAliceBob = crypto.diffieHellman({
125+
privateKey: alicePrivate,
126+
publicKey: bobPublic,
127+
}) as Buffer;
128+
129+
const secretAliceCharlie = crypto.diffieHellman({
130+
privateKey: alicePrivate,
131+
publicKey: charliePublic,
132+
}) as Buffer;
133+
134+
// Different public keys should produce different shared secrets
135+
void expect(secretAliceBob.equals(secretAliceCharlie)).to.be.false;
136+
});
137+
138+
test(SUITE, 'x25519 - error handling', () => {
139+
const alice = crypto.generateKeyPairSync('x25519', {});
140+
141+
const alicePrivate = KeyObject.createKeyObject(
142+
'private',
143+
alice.privateKey as ArrayBuffer,
144+
);
145+
146+
// Should throw when creating KeyObject with invalid key data
147+
void expect(() => {
148+
KeyObject.createKeyObject('public', new ArrayBuffer(16)); // Invalid size
149+
}).to.throw();
150+
151+
// Should throw when using invalid key types
152+
void expect(() => {
153+
crypto.diffieHellman({
154+
privateKey: alicePrivate,
155+
publicKey: {} as KeyObject,
156+
});
157+
}).to.throw();
158+
});

packages/react-native-quick-crypto/android/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ add_library(
1919
../cpp/hash/HybridHash.cpp
2020
../cpp/hmac/HybridHmac.cpp
2121
../cpp/keys/HybridKeyObjectHandle.cpp
22+
../cpp/keys/KeyObjectData.cpp
2223
../cpp/pbkdf2/HybridPbkdf2.cpp
2324
../cpp/random/HybridRandom.cpp
2425
../deps/fastpbkdf2/fastpbkdf2.c
26+
../deps/ncrypto/src/ncrypto.cpp
2527
)
2628

2729
# add Nitrogen specs
@@ -39,7 +41,7 @@ include_directories(
3941
"../cpp/random"
4042
"../cpp/utils"
4143
"../deps/fastpbkdf2"
42-
"../deps/ncrypto"
44+
"../deps/ncrypto/include"
4345
"../build/includes" # flattened Nitro Modules headers
4446
"../../../node_modules/react-native/ReactCommon/jsi"
4547
)
@@ -55,6 +57,7 @@ target_link_libraries(
5557
${LOG_LIB} # <-- Logcat logger
5658
android # <-- Android core
5759
openssl::crypto # <-- OpenSSL (Crypto)
60+
openssl::ssl # <-- OpenSSL (SSL)
5861
)
5962

6063
if(SODIUM_ENABLED)

packages/react-native-quick-crypto/cpp/keys/HybridKeyObjectHandle.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ bool HybridKeyObjectHandle::initRawKey(KeyType keyType, std::shared_ptr<ArrayBuf
191191
} else if (keySize == 57) {
192192
curveId = EVP_PKEY_ED448;
193193
} else {
194-
return false; // Unsupported key size
194+
throw std::runtime_error("Invalid key size: expected 32, 56, or 57 bytes for curve keys");
195195
}
196196

197197
ncrypto::Buffer<const unsigned char> buffer{
@@ -205,11 +205,11 @@ bool HybridKeyObjectHandle::initRawKey(KeyType keyType, std::shared_ptr<ArrayBuf
205205
} else if (keyType == KeyType::PUBLIC) {
206206
pkey = ncrypto::EVPKeyPointer::NewRawPublic(curveId, buffer);
207207
} else {
208-
return false; // Raw keys are only for asymmetric keys
208+
throw std::runtime_error("Raw keys are only supported for asymmetric key types");
209209
}
210210

211211
if (!pkey) {
212-
return false;
212+
throw std::runtime_error("Failed to create key from raw data");
213213
}
214214

215215
this->data_ = KeyObjectData::CreateAsymmetric(keyType, std::move(pkey));

packages/react-native-quick-crypto/cpp/keys/KeyObjectData.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,39 @@ KeyObjectData KeyObjectData::CreateAsymmetric(KeyType key_type,
5555
}
5656

5757
KeyType KeyObjectData::GetKeyType() const {
58-
CHECK(data_);
58+
if (!data_) {
59+
throw std::runtime_error("Invalid key object: no key data available");
60+
}
5961
return key_type_;
6062
}
6163

6264
const ncrypto::EVPKeyPointer& KeyObjectData::GetAsymmetricKey() const {
63-
CHECK_NE(key_type_, KeyType::SECRET);
64-
CHECK(data_);
65+
if (key_type_ == KeyType::SECRET) {
66+
throw std::runtime_error("Cannot get asymmetric key from secret key object");
67+
}
68+
if (!data_) {
69+
throw std::runtime_error("Invalid key object: no key data available");
70+
}
6571
return data_->asymmetric_key;
6672
}
6773

6874
std::shared_ptr<ArrayBuffer> KeyObjectData::GetSymmetricKey() const {
69-
CHECK_EQ(key_type_, KeyType::SECRET);
70-
CHECK(data_);
75+
if (key_type_ != KeyType::SECRET) {
76+
throw std::runtime_error("Cannot get symmetric key from asymmetric key object");
77+
}
78+
if (!data_) {
79+
throw std::runtime_error("Invalid key object: no key data available");
80+
}
7181
return data_->symmetric_key;
7282
}
7383

7484
size_t KeyObjectData::GetSymmetricKeySize() const {
75-
CHECK_EQ(key_type_, KeyType::SECRET);
76-
CHECK(data_);
85+
if (key_type_ != KeyType::SECRET) {
86+
throw std::runtime_error("Cannot get symmetric key size from asymmetric key object");
87+
}
88+
if (!data_) {
89+
throw std::runtime_error("Invalid key object: no key data available");
90+
}
7791
return data_->symmetric_key->size();
7892
}
7993

packages/react-native-quick-crypto/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@
8686
"del-cli": "6.0.0",
8787
"expo": "^47.0.0",
8888
"jest": "29.7.0",
89-
"nitro-codegen": "0.26.2",
89+
"nitro-codegen": "0.26.4",
9090
"react-native-builder-bob": "0.39.1",
91-
"react-native-nitro-modules": "0.26.2"
91+
"react-native-nitro-modules": "0.26.4"
9292
},
9393
"peerDependencies": {
9494
"react": "*",
9595
"react-native": "*",
96-
"react-native-nitro-modules": ">=0.26.2",
96+
"react-native-nitro-modules": ">=0.26.4",
9797
"expo": ">=47.0.0"
9898
},
9999
"peerDependenciesMeta": {

0 commit comments

Comments
 (0)