one 2.6.20 → 2.6.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/android/src/main/java/dev/onejs/onenative/OneNativeCameraManager.kt +24 -0
  2. package/android/src/main/java/dev/onejs/onenative/OneNativeCameraView.kt +197 -2
  3. package/cpp/HybridOneCrypto.cpp +327 -1
  4. package/cpp/HybridOneCrypto.hpp +8 -0
  5. package/dist/cjs/index.cjs +25 -22
  6. package/dist/cjs/index.native.cjs +25 -22
  7. package/dist/cjs/index.native.js +25 -22
  8. package/dist/cjs/index.native.js.map +1 -1
  9. package/dist/cjs/one.cjs +1 -0
  10. package/dist/cjs/one.native.cjs +1 -0
  11. package/dist/cjs/one.native.js +1 -0
  12. package/dist/cjs/one.native.js.map +1 -1
  13. package/dist/cjs/platform/camera/index.cjs +3 -2
  14. package/dist/cjs/platform/camera/index.native.cjs +89 -3
  15. package/dist/cjs/platform/camera/index.native.js +89 -3
  16. package/dist/cjs/platform/camera/index.native.js.map +1 -1
  17. package/dist/cjs/platform/crypto/aes.cjs +259 -0
  18. package/dist/cjs/platform/crypto/aes.native.cjs +343 -0
  19. package/dist/cjs/platform/crypto/aes.native.js +345 -0
  20. package/dist/cjs/platform/crypto/aes.native.js.map +1 -0
  21. package/dist/cjs/platform/crypto/bytes.cjs +132 -0
  22. package/dist/cjs/platform/crypto/bytes.native.cjs +175 -0
  23. package/dist/cjs/platform/crypto/bytes.native.js +177 -0
  24. package/dist/cjs/platform/crypto/bytes.native.js.map +1 -0
  25. package/dist/cjs/platform/crypto/digest-api.cjs +65 -0
  26. package/dist/cjs/platform/crypto/digest-api.native.cjs +69 -0
  27. package/dist/cjs/platform/crypto/digest-api.native.js +71 -0
  28. package/dist/cjs/platform/crypto/digest-api.native.js.map +1 -0
  29. package/dist/cjs/platform/crypto/digest.cjs +26 -15
  30. package/dist/cjs/platform/crypto/digest.native.cjs +26 -15
  31. package/dist/cjs/platform/crypto/digest.native.js +26 -15
  32. package/dist/cjs/platform/crypto/digest.native.js.map +1 -1
  33. package/dist/cjs/platform/crypto/index.cjs +19 -1
  34. package/dist/cjs/platform/crypto/index.native.cjs +39 -1
  35. package/dist/cjs/platform/crypto/index.native.js +39 -1
  36. package/dist/cjs/platform/crypto/index.native.js.map +1 -1
  37. package/dist/cjs/platform/crypto/types.cjs +16 -0
  38. package/dist/cjs/platform/crypto/types.native.cjs +18 -0
  39. package/dist/cjs/platform/crypto/types.native.js +20 -0
  40. package/dist/cjs/platform/crypto/types.native.js.map +1 -0
  41. package/dist/cjs/platform/crypto/web.cjs +73 -0
  42. package/dist/cjs/platform/extras.cjs +4 -0
  43. package/dist/cjs/platform/extras.native.cjs +4 -0
  44. package/dist/cjs/platform/extras.native.js +4 -0
  45. package/dist/cjs/platform/extras.native.js.map +1 -1
  46. package/dist/cjs/platform/specs/OneNativeCameraNativeComponent.cjs +37 -21
  47. package/dist/cjs/platform/specs/OneNativeCameraNativeComponent.native.cjs +37 -21
  48. package/dist/cjs/platform/specs/OneNativeCameraNativeComponent.native.js +37 -21
  49. package/dist/cjs/platform/specs/OneNativeCameraNativeComponent.native.js.map +3 -3
  50. package/dist/cjs/router/router.cjs +4 -1
  51. package/dist/esm/index.js +2 -2
  52. package/dist/esm/index.mjs +2 -2
  53. package/dist/esm/index.native.js +2 -2
  54. package/dist/esm/one.mjs +2 -1
  55. package/dist/esm/one.mjs.map +1 -1
  56. package/dist/esm/one.native.js +2 -1
  57. package/dist/esm/one.native.js.map +1 -1
  58. package/dist/esm/platform/camera/index.mjs +4 -2
  59. package/dist/esm/platform/camera/index.mjs.map +1 -1
  60. package/dist/esm/platform/camera/index.native.js +90 -4
  61. package/dist/esm/platform/camera/index.native.js.map +1 -1
  62. package/dist/esm/platform/crypto/aes.mjs +236 -0
  63. package/dist/esm/platform/crypto/aes.mjs.map +1 -0
  64. package/dist/esm/platform/crypto/aes.native.js +318 -0
  65. package/dist/esm/platform/crypto/aes.native.js.map +1 -0
  66. package/dist/esm/platform/crypto/bytes.mjs +104 -0
  67. package/dist/esm/platform/crypto/bytes.mjs.map +1 -0
  68. package/dist/esm/platform/crypto/bytes.native.js +145 -0
  69. package/dist/esm/platform/crypto/bytes.native.js.map +1 -0
  70. package/dist/esm/platform/crypto/digest-api.mjs +42 -0
  71. package/dist/esm/platform/crypto/digest-api.mjs.map +1 -0
  72. package/dist/esm/platform/crypto/digest-api.native.js +44 -0
  73. package/dist/esm/platform/crypto/digest-api.native.js.map +1 -0
  74. package/dist/esm/platform/crypto/digest.mjs +23 -15
  75. package/dist/esm/platform/crypto/digest.mjs.map +1 -1
  76. package/dist/esm/platform/crypto/digest.native.js +23 -15
  77. package/dist/esm/platform/crypto/digest.native.js.map +1 -1
  78. package/dist/esm/platform/crypto/index.mjs +14 -1
  79. package/dist/esm/platform/crypto/index.mjs.map +1 -1
  80. package/dist/esm/platform/crypto/index.native.js +34 -1
  81. package/dist/esm/platform/crypto/index.native.js.map +1 -1
  82. package/dist/esm/platform/crypto/types.mjs +0 -0
  83. package/dist/esm/platform/crypto/types.native.js +0 -0
  84. package/dist/esm/platform/crypto/web.mjs +50 -0
  85. package/dist/esm/platform/crypto/web.mjs.map +1 -0
  86. package/dist/esm/platform/extras.mjs +2 -1
  87. package/dist/esm/platform/extras.native.js +2 -1
  88. package/dist/esm/platform/specs/OneNativeCameraNativeComponent.mjs +25 -9
  89. package/dist/esm/platform/specs/OneNativeCameraNativeComponent.mjs.map +3 -3
  90. package/dist/esm/platform/specs/OneNativeCameraNativeComponent.native.js +25 -9
  91. package/dist/esm/platform/specs/OneNativeCameraNativeComponent.native.js.map +3 -3
  92. package/dist/esm/router/router.mjs +5 -2
  93. package/dist/esm/router/router.mjs.map +1 -1
  94. package/ios/OneNativeCameraComponentView.mm +28 -0
  95. package/ios/OneNativeCameraView.swift +163 -0
  96. package/nitrogen/generated/shared/c++/HybridOneCryptoSpec.cpp +2 -0
  97. package/nitrogen/generated/shared/c++/HybridOneCryptoSpec.hpp +4 -1
  98. package/package.json +12 -12
  99. package/src/index.ts +4 -0
  100. package/src/one.ts +3 -0
  101. package/src/platform/camera/index.native.tsx +116 -12
  102. package/src/platform/camera/index.tsx +15 -4
  103. package/src/platform/camera/types.ts +22 -0
  104. package/src/platform/crypto/aes.ts +345 -0
  105. package/src/platform/crypto/bytes.ts +120 -0
  106. package/src/platform/crypto/digest-api.ts +50 -0
  107. package/src/platform/crypto/digest.ts +24 -15
  108. package/src/platform/crypto/index.native.ts +68 -0
  109. package/src/platform/crypto/index.ts +31 -0
  110. package/src/platform/crypto/types.ts +64 -0
  111. package/src/platform/crypto/web.ts +69 -0
  112. package/src/platform/extras.ts +15 -0
  113. package/src/platform/index.native.ts +4 -0
  114. package/src/platform/index.ts +4 -0
  115. package/src/platform/specs/OneCrypto.nitro.ts +19 -0
  116. package/src/platform/specs/OneNativeCameraNativeComponent.ts +35 -2
  117. package/src/router/router.ts +7 -4
  118. package/types/index.d.ts +2 -1
  119. package/types/index.d.ts.map +1 -1
  120. package/types/one.d.ts +2 -1
  121. package/types/one.d.ts.map +1 -1
  122. package/types/platform/camera/index.d.ts +3 -3
  123. package/types/platform/camera/index.d.ts.map +1 -1
  124. package/types/platform/camera/index.native.d.ts +3 -3
  125. package/types/platform/camera/index.native.d.ts.map +1 -1
  126. package/types/platform/camera/types.d.ts +18 -0
  127. package/types/platform/camera/types.d.ts.map +1 -1
  128. package/types/platform/crypto/aes.d.ts +211 -0
  129. package/types/platform/crypto/aes.d.ts.map +1 -0
  130. package/types/platform/crypto/bytes.d.ts +8 -0
  131. package/types/platform/crypto/bytes.d.ts.map +1 -0
  132. package/types/platform/crypto/digest-api.d.ts +9 -0
  133. package/types/platform/crypto/digest-api.d.ts.map +1 -0
  134. package/types/platform/crypto/digest.d.ts +5 -0
  135. package/types/platform/crypto/digest.d.ts.map +1 -1
  136. package/types/platform/crypto/index.d.ts +127 -0
  137. package/types/platform/crypto/index.d.ts.map +1 -1
  138. package/types/platform/crypto/index.native.d.ts +127 -0
  139. package/types/platform/crypto/index.native.d.ts.map +1 -1
  140. package/types/platform/crypto/types.d.ts +43 -0
  141. package/types/platform/crypto/types.d.ts.map +1 -0
  142. package/types/platform/crypto/web.d.ts +5 -0
  143. package/types/platform/crypto/web.d.ts.map +1 -0
  144. package/types/platform/extras.d.ts +2 -0
  145. package/types/platform/extras.d.ts.map +1 -1
  146. package/types/platform/index.d.ts +1 -1
  147. package/types/platform/index.d.ts.map +1 -1
  148. package/types/platform/index.native.d.ts +1 -1
  149. package/types/platform/index.native.d.ts.map +1 -1
  150. package/types/platform/specs/OneCrypto.nitro.d.ts +2 -0
  151. package/types/platform/specs/OneCrypto.nitro.d.ts.map +1 -1
  152. package/types/platform/specs/OneNativeCameraNativeComponent.d.ts +18 -2
  153. package/types/platform/specs/OneNativeCameraNativeComponent.d.ts.map +1 -1
  154. package/types/router/router.d.ts.map +1 -1
@@ -1,11 +1,14 @@
1
1
  #include "HybridOneCrypto.hpp"
2
2
 
3
3
  #include <algorithm>
4
+ #include <array>
5
+ #include <optional>
4
6
  #include <cstring>
5
7
  #include <vector>
6
8
  #ifdef __ANDROID__
7
9
  #include <fbjni/fbjni.h>
8
10
  #else
11
+ #include <CommonCrypto/CommonCryptor.h>
9
12
  #include <CommonCrypto/CommonDigest.h>
10
13
  #endif
11
14
  #include <cmath>
@@ -54,6 +57,94 @@ std::shared_ptr<ArrayBuffer> hash(const std::string& algorithm, const std::vecto
54
57
  digest->getRegion(0, digest->size(), reinterpret_cast<jbyte*>(output->data()));
55
58
  return output;
56
59
  }
60
+
61
+ // jni resolves methods by exact descriptor, so Cipher.init's parameters are
62
+ // declared as the api's own types, Key and AlgorithmParameterSpec, and the
63
+ // concrete specs derive from them so they pass without a cast.
64
+ class Key : public facebook::jni::JavaClass<Key> {
65
+ public:
66
+ static constexpr auto kJavaDescriptor = "Ljava/security/Key;";
67
+ };
68
+
69
+ class AlgorithmParameterSpec : public facebook::jni::JavaClass<AlgorithmParameterSpec> {
70
+ public:
71
+ static constexpr auto kJavaDescriptor = "Ljava/security/spec/AlgorithmParameterSpec;";
72
+ };
73
+
74
+ class SecretKeySpec : public facebook::jni::JavaClass<SecretKeySpec, Key> {
75
+ public:
76
+ static constexpr auto kJavaDescriptor = "Ljavax/crypto/spec/SecretKeySpec;";
77
+
78
+ static facebook::jni::local_ref<SecretKeySpec> create(facebook::jni::alias_ref<facebook::jni::JArrayByte> key) {
79
+ return newInstance(key, facebook::jni::make_jstring("AES"));
80
+ }
81
+ };
82
+
83
+ class GCMParameterSpec : public facebook::jni::JavaClass<GCMParameterSpec, AlgorithmParameterSpec> {
84
+ public:
85
+ static constexpr auto kJavaDescriptor = "Ljavax/crypto/spec/GCMParameterSpec;";
86
+
87
+ static facebook::jni::local_ref<GCMParameterSpec> create(jint tagBits, facebook::jni::alias_ref<facebook::jni::JArrayByte> iv) {
88
+ return newInstance(tagBits, iv);
89
+ }
90
+ };
91
+
92
+ class Cipher : public facebook::jni::JavaClass<Cipher> {
93
+ public:
94
+ static constexpr auto kJavaDescriptor = "Ljavax/crypto/Cipher;";
95
+ static constexpr jint ENCRYPT_MODE = 1;
96
+ static constexpr jint DECRYPT_MODE = 2;
97
+
98
+ static facebook::jni::local_ref<Cipher> create() {
99
+ static const auto method = javaClassStatic()->getStaticMethod<facebook::jni::local_ref<Cipher>(facebook::jni::alias_ref<facebook::jni::JString>)>("getInstance");
100
+ return method(javaClassStatic(), facebook::jni::make_jstring("AES/GCM/NoPadding"));
101
+ }
102
+
103
+ void init(jint mode, facebook::jni::alias_ref<SecretKeySpec> key, facebook::jni::alias_ref<GCMParameterSpec> spec) {
104
+ static const auto method = javaClassStatic()->getMethod<void(jint, facebook::jni::alias_ref<Key>, facebook::jni::alias_ref<AlgorithmParameterSpec>)>("init");
105
+ method(self(), mode, key, spec);
106
+ }
107
+
108
+ void updateAAD(facebook::jni::alias_ref<facebook::jni::JArrayByte> aad) {
109
+ static const auto method = javaClassStatic()->getMethod<void(facebook::jni::alias_ref<facebook::jni::JArrayByte>)>("updateAAD");
110
+ method(self(), aad);
111
+ }
112
+
113
+ facebook::jni::local_ref<facebook::jni::JArrayByte> doFinal(facebook::jni::alias_ref<facebook::jni::JArrayByte> input) {
114
+ static const auto method = javaClassStatic()->getMethod<facebook::jni::local_ref<facebook::jni::JArrayByte>(facebook::jni::alias_ref<facebook::jni::JArrayByte>)>("doFinal");
115
+ return method(self(), input);
116
+ }
117
+ };
118
+
119
+ facebook::jni::local_ref<facebook::jni::JArrayByte> toJavaBytes(const std::vector<uint8_t>& bytes) {
120
+ auto out = facebook::jni::JArrayByte::newArray(bytes.size());
121
+ if (!bytes.empty()) out->setRegion(0, static_cast<jint>(bytes.size()), reinterpret_cast<const jbyte*>(bytes.data()));
122
+ return out;
123
+ }
124
+
125
+ std::shared_ptr<ArrayBuffer> fromJavaBytes(facebook::jni::alias_ref<facebook::jni::JArrayByte> bytes) {
126
+ auto out = ArrayBuffer::allocate(bytes->size());
127
+ if (bytes->size() > 0) bytes->getRegion(0, bytes->size(), reinterpret_cast<jbyte*>(out->data()));
128
+ return out;
129
+ }
130
+
131
+ // javax.crypto does the whole AEAD: seal appends the tag, open verifies it
132
+ // and throws AEADBadTagException, which surfaces here as a jni exception.
133
+ std::shared_ptr<ArrayBuffer> aesGcm(bool encrypt, const std::vector<uint8_t>& key, const std::vector<uint8_t>& iv,
134
+ const std::vector<uint8_t>& input, const std::optional<std::vector<uint8_t>>& aad,
135
+ size_t tagLength) {
136
+ facebook::jni::ThreadScope scope;
137
+ auto cipher = Cipher::create();
138
+ auto spec = GCMParameterSpec::create(static_cast<jint>(tagLength * 8), toJavaBytes(iv));
139
+ cipher->init(encrypt ? Cipher::ENCRYPT_MODE : Cipher::DECRYPT_MODE, SecretKeySpec::create(toJavaBytes(key)), spec);
140
+ if (aad && !aad->empty()) cipher->updateAAD(toJavaBytes(*aad));
141
+ try {
142
+ return fromJavaBytes(cipher->doFinal(toJavaBytes(input)));
143
+ } catch (const std::exception&) {
144
+ if (!encrypt) throw std::runtime_error("aesDecrypt: authentication failed");
145
+ throw;
146
+ }
147
+ }
57
148
  #else
58
149
  template <typename Context, auto Init, auto Update, auto Final>
59
150
  std::shared_ptr<ArrayBuffer> hashApple(const std::vector<uint8_t>& input, size_t size) {
@@ -72,18 +163,186 @@ std::shared_ptr<ArrayBuffer> hashApple(const std::vector<uint8_t>& input, size_t
72
163
  }
73
164
 
74
165
  std::shared_ptr<ArrayBuffer> hash(const std::string& algorithm, const std::vector<uint8_t>& input) {
166
+ if (algorithm == "MD5") return hashApple<CC_MD5_CTX, CC_MD5_Init, CC_MD5_Update, CC_MD5_Final>(input, CC_MD5_DIGEST_LENGTH);
75
167
  if (algorithm == "SHA-1") return hashApple<CC_SHA1_CTX, CC_SHA1_Init, CC_SHA1_Update, CC_SHA1_Final>(input, CC_SHA1_DIGEST_LENGTH);
76
168
  if (algorithm == "SHA-256") return hashApple<CC_SHA256_CTX, CC_SHA256_Init, CC_SHA256_Update, CC_SHA256_Final>(input, CC_SHA256_DIGEST_LENGTH);
77
169
  if (algorithm == "SHA-384") return hashApple<CC_SHA512_CTX, CC_SHA384_Init, CC_SHA384_Update, CC_SHA384_Final>(input, CC_SHA384_DIGEST_LENGTH);
78
170
  if (algorithm == "SHA-512") return hashApple<CC_SHA512_CTX, CC_SHA512_Init, CC_SHA512_Update, CC_SHA512_Final>(input, CC_SHA512_DIGEST_LENGTH);
79
171
  throw std::runtime_error("unsupported digest algorithm");
80
172
  }
173
+
174
+ // AES-GCM over CommonCrypto's public AES block primitive: the public headers
175
+ // have no GCM helper, so CTR and GHASH are composed here per NIST SP
176
+ // 800-38D. counter blocks are encrypted in one ECB pass (ECB over distinct
177
+ // counters is exactly GCM's CTR keystream), and the tag is always 16 bytes,
178
+ // as in expo-crypto on apple platforms.
179
+ using Block = std::array<uint8_t, 16>;
180
+
181
+ void aesEcb(const std::vector<uint8_t>& key, const uint8_t* input, size_t length, uint8_t* output) {
182
+ CCCryptorRef cryptor = nullptr;
183
+ auto status = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES, ccNoPadding, nullptr, key.data(),
184
+ key.size(), nullptr, 0, 0, 0, &cryptor);
185
+ if (status != kCCSuccess || cryptor == nullptr) throw std::runtime_error("aes: cipher creation failed");
186
+ size_t moved = 0;
187
+ status = CCCryptorUpdate(cryptor, input, length, output, length, &moved);
188
+ CCCryptorRelease(cryptor);
189
+ if (status != kCCSuccess || moved != length) throw std::runtime_error("aes: block encryption failed");
190
+ }
191
+
192
+ Block aesBlock(const std::vector<uint8_t>& key, const Block& input) {
193
+ Block output{};
194
+ aesEcb(key, input.data(), input.size(), output.data());
195
+ return output;
196
+ }
197
+
198
+ uint64_t load64(const uint8_t* at) {
199
+ uint64_t value = 0;
200
+ for (int i = 0; i < 8; i++) value = (value << 8) | at[i];
201
+ return value;
202
+ }
203
+
204
+ void store64(uint8_t* at, uint64_t value) {
205
+ for (int i = 7; i >= 0; i--) {
206
+ at[i] = static_cast<uint8_t>(value);
207
+ value >>= 8;
208
+ }
209
+ }
210
+
211
+ // GF(2^128) multiplication, NIST SP 800-38D algorithm 1, with the reduction
212
+ // constant R = 11100001 || 0^120. both operands carry bits of the hash key,
213
+ // so every step selects with masks instead of branching: the running time
214
+ // never depends on the key.
215
+ Block gfMultiply(const Block& x, const Block& y) {
216
+ uint64_t zh = 0, zl = 0;
217
+ uint64_t vh = load64(y.data()), vl = load64(y.data() + 8);
218
+ for (int i = 0; i < 16; i++) {
219
+ for (int bit = 7; bit >= 0; bit--) {
220
+ const uint64_t take = 0 - static_cast<uint64_t>((x[i] >> bit) & 1);
221
+ zh ^= vh & take;
222
+ zl ^= vl & take;
223
+ const uint64_t carry = 0 - (vl & 1);
224
+ vl = (vl >> 1) | (vh << 63);
225
+ vh = (vh >> 1) ^ (0xe100000000000000ULL & carry);
226
+ }
227
+ }
228
+ Block out{};
229
+ store64(out.data(), zh);
230
+ store64(out.data() + 8, zl);
231
+ return out;
232
+ }
233
+
234
+ Block ghash(const Block& h, const uint8_t* data, size_t length, Block state) {
235
+ for (size_t at = 0; at < length; at += 16) {
236
+ Block block{};
237
+ std::memcpy(block.data(), data + at, std::min<size_t>(16, length - at));
238
+ for (int i = 0; i < 16; i++) state[i] ^= block[i];
239
+ state = gfMultiply(state, h);
240
+ }
241
+ return state;
242
+ }
243
+
244
+ Block ghashAll(const Block& h, const std::optional<std::vector<uint8_t>>& aad, const std::vector<uint8_t>& ciphertext) {
245
+ Block state{};
246
+ if (aad && !aad->empty()) state = ghash(h, aad->data(), aad->size(), state);
247
+ if (!ciphertext.empty()) state = ghash(h, ciphertext.data(), ciphertext.size(), state);
248
+ Block lengths{};
249
+ store64(lengths.data(), static_cast<uint64_t>(aad ? aad->size() : 0) * 8);
250
+ store64(lengths.data() + 8, static_cast<uint64_t>(ciphertext.size()) * 8);
251
+ for (int i = 0; i < 16; i++) state[i] ^= lengths[i];
252
+ return gfMultiply(state, h);
253
+ }
254
+
255
+ Block initialCounter(const Block& h, const std::vector<uint8_t>& iv) {
256
+ if (iv.size() == 12) {
257
+ Block j0{};
258
+ std::memcpy(j0.data(), iv.data(), 12);
259
+ j0[15] = 1;
260
+ return j0;
261
+ }
262
+ Block state = ghash(h, iv.data(), iv.size(), Block{});
263
+ Block lengths{};
264
+ store64(lengths.data() + 8, static_cast<uint64_t>(iv.size()) * 8);
265
+ for (int i = 0; i < 16; i++) state[i] ^= lengths[i];
266
+ return gfMultiply(state, h);
267
+ }
268
+
269
+ void increment32(Block& counter) {
270
+ uint32_t low = (static_cast<uint32_t>(counter[12]) << 24) | (static_cast<uint32_t>(counter[13]) << 16) |
271
+ (static_cast<uint32_t>(counter[14]) << 8) | counter[15];
272
+ low += 1;
273
+ counter[12] = static_cast<uint8_t>(low >> 24);
274
+ counter[13] = static_cast<uint8_t>(low >> 16);
275
+ counter[14] = static_cast<uint8_t>(low >> 8);
276
+ counter[15] = static_cast<uint8_t>(low);
277
+ }
278
+
279
+ std::vector<uint8_t> gctr(const std::vector<uint8_t>& key, Block j0, const std::vector<uint8_t>& input) {
280
+ std::vector<uint8_t> output(input.size());
281
+ if (input.empty()) return output;
282
+ const size_t blocks = (input.size() + 15) / 16;
283
+ std::vector<uint8_t> counters(blocks * 16);
284
+ Block counter = j0;
285
+ for (size_t i = 0; i < blocks; i++) {
286
+ increment32(counter);
287
+ std::memcpy(counters.data() + i * 16, counter.data(), 16);
288
+ }
289
+ std::vector<uint8_t> keystream(counters.size());
290
+ aesEcb(key, counters.data(), counters.size(), keystream.data());
291
+ for (size_t i = 0; i < input.size(); i++) output[i] = input[i] ^ keystream[i];
292
+ return output;
293
+ }
294
+
295
+ Block computeTag(const std::vector<uint8_t>& key, const Block& h, const Block& j0,
296
+ const std::optional<std::vector<uint8_t>>& aad, const std::vector<uint8_t>& ciphertext) {
297
+ Block s = ghashAll(h, aad, ciphertext);
298
+ Block mask = aesBlock(key, j0);
299
+ for (int i = 0; i < 16; i++) s[i] ^= mask[i];
300
+ return s;
301
+ }
302
+
303
+ std::shared_ptr<ArrayBuffer> aesGcmOpen(const std::vector<uint8_t>& key, const std::vector<uint8_t>& iv,
304
+ const std::vector<uint8_t>& input, const std::optional<std::vector<uint8_t>>& aad,
305
+ size_t tagLength);
306
+
307
+ std::shared_ptr<ArrayBuffer> aesGcm(bool encrypt, const std::vector<uint8_t>& key, const std::vector<uint8_t>& iv,
308
+ const std::vector<uint8_t>& input, const std::optional<std::vector<uint8_t>>& aad,
309
+ size_t tagLength) {
310
+ if (!encrypt) return aesGcmOpen(key, iv, input, aad, tagLength);
311
+ const Block h = aesBlock(key, Block{});
312
+ const Block j0 = initialCounter(h, iv);
313
+ if (encrypt) {
314
+ auto ciphertext = gctr(key, j0, input);
315
+ Block tag = computeTag(key, h, j0, aad, ciphertext);
316
+ auto out = ArrayBuffer::allocate(ciphertext.size() + 16);
317
+ if (!ciphertext.empty()) std::memcpy(out->data(), ciphertext.data(), ciphertext.size());
318
+ std::memcpy(out->data() + ciphertext.size(), tag.data(), 16);
319
+ return out;
320
+ }
321
+ throw std::runtime_error("aes: unreachable");
322
+ }
323
+
324
+ std::shared_ptr<ArrayBuffer> aesGcmOpen(const std::vector<uint8_t>& key, const std::vector<uint8_t>& iv,
325
+ const std::vector<uint8_t>& input, const std::optional<std::vector<uint8_t>>& aad,
326
+ size_t tagLength) {
327
+ if (input.size() < tagLength) throw std::runtime_error("aesDecrypt: authentication failed");
328
+ const Block h = aesBlock(key, Block{});
329
+ const Block j0 = initialCounter(h, iv);
330
+ std::vector<uint8_t> ciphertext(input.begin(), input.end() - static_cast<ptrdiff_t>(tagLength));
331
+ Block expected = computeTag(key, h, j0, aad, ciphertext);
332
+ uint8_t diff = 0;
333
+ for (size_t i = 0; i < tagLength; i++) diff |= expected[i] ^ input[ciphertext.size() + i];
334
+ if (diff != 0) throw std::runtime_error("aesDecrypt: authentication failed");
335
+ auto plain = gctr(key, j0, ciphertext);
336
+ auto out = ArrayBuffer::allocate(plain.size());
337
+ if (!plain.empty()) std::memcpy(out->data(), plain.data(), plain.size());
338
+ return out;
339
+ }
81
340
  #endif
82
341
  } // namespace
83
342
 
84
343
  std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridOneCrypto::digest(
85
344
  const std::string& algorithm, const std::shared_ptr<ArrayBuffer>& buffer, double offset, double length) {
86
- if (algorithm != "SHA-1" && algorithm != "SHA-256" && algorithm != "SHA-384" && algorithm != "SHA-512") {
345
+ if (algorithm != "MD5" && algorithm != "SHA-1" && algorithm != "SHA-256" && algorithm != "SHA-384" && algorithm != "SHA-512") {
87
346
  throw std::runtime_error("unsupported digest algorithm");
88
347
  }
89
348
  if (!(offset >= 0 && length >= 0 && offset == std::floor(offset) && length == std::floor(length) &&
@@ -99,6 +358,73 @@ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridOneCrypto::digest(
99
358
  });
100
359
  }
101
360
 
361
+
362
+ namespace {
363
+ std::vector<uint8_t> snapshot(const std::shared_ptr<ArrayBuffer>& buffer) {
364
+ std::vector<uint8_t> out(buffer->size());
365
+ if (!out.empty()) std::memcpy(out.data(), buffer->data(), out.size());
366
+ return out;
367
+ }
368
+
369
+ std::optional<std::vector<uint8_t>> snapshot(const std::optional<std::shared_ptr<ArrayBuffer>>& buffer) {
370
+ if (!buffer) return std::nullopt;
371
+ return snapshot(*buffer);
372
+ }
373
+
374
+ void assertKeyAndIv(const std::vector<uint8_t>& key, const std::vector<uint8_t>& iv, const char* verb) {
375
+ if (key.size() != 16 && key.size() != 24 && key.size() != 32) {
376
+ throw std::runtime_error(std::string(verb) + ": key must be 128, 192, or 256 bits");
377
+ }
378
+ if (iv.empty()) throw std::runtime_error(std::string(verb) + ": iv must not be empty");
379
+ }
380
+
381
+ // gcm's allowed tag lengths in bytes. decrypt checks them too: a zero tag
382
+ // would compare nothing and accept any ciphertext, and one over 16 would read
383
+ // past the computed tag.
384
+ void assertTagLength(double tagLength, const char* verb) {
385
+ for (double allowed : {16.0, 15.0, 14.0, 13.0, 12.0, 8.0, 4.0}) {
386
+ if (tagLength == allowed) return;
387
+ }
388
+ throw std::runtime_error(std::string(verb) + ": unsupported tag length");
389
+ }
390
+ } // namespace
391
+
392
+ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridOneCrypto::aesEncrypt(
393
+ const std::shared_ptr<ArrayBuffer>& key, const std::shared_ptr<ArrayBuffer>& iv,
394
+ const std::shared_ptr<ArrayBuffer>& plaintext, const std::optional<std::shared_ptr<ArrayBuffer>>& additionalData,
395
+ double tagLength) {
396
+ // snapshot every input on the calling js thread, like digest: a borrowed
397
+ // jsi buffer must never be read on a worker or after the caller mutates it.
398
+ auto keyCopy = snapshot(key);
399
+ auto ivCopy = snapshot(iv);
400
+ auto plainCopy = snapshot(plaintext);
401
+ auto aadCopy = snapshot(additionalData);
402
+ assertKeyAndIv(keyCopy, ivCopy, "aesEncrypt");
403
+ assertTagLength(tagLength, "aesEncrypt");
404
+ return Promise<std::shared_ptr<ArrayBuffer>>::async(
405
+ [keyCopy = std::move(keyCopy), ivCopy = std::move(ivCopy), plainCopy = std::move(plainCopy),
406
+ aadCopy = std::move(aadCopy), tagLength]() {
407
+ return aesGcm(true, keyCopy, ivCopy, plainCopy, aadCopy, static_cast<size_t>(tagLength));
408
+ });
409
+ }
410
+
411
+ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridOneCrypto::aesDecrypt(
412
+ const std::shared_ptr<ArrayBuffer>& key, const std::shared_ptr<ArrayBuffer>& iv,
413
+ const std::shared_ptr<ArrayBuffer>& ciphertext, const std::optional<std::shared_ptr<ArrayBuffer>>& additionalData,
414
+ double tagLength) {
415
+ auto keyCopy = snapshot(key);
416
+ auto ivCopy = snapshot(iv);
417
+ auto cipherCopy = snapshot(ciphertext);
418
+ auto aadCopy = snapshot(additionalData);
419
+ assertKeyAndIv(keyCopy, ivCopy, "aesDecrypt");
420
+ assertTagLength(tagLength, "aesDecrypt");
421
+ return Promise<std::shared_ptr<ArrayBuffer>>::async(
422
+ [keyCopy = std::move(keyCopy), ivCopy = std::move(ivCopy), cipherCopy = std::move(cipherCopy),
423
+ aadCopy = std::move(aadCopy), tagLength]() {
424
+ return aesGcm(false, keyCopy, ivCopy, cipherCopy, aadCopy, static_cast<size_t>(tagLength));
425
+ });
426
+ }
427
+
102
428
  void HybridOneCrypto::fillRandomBytes(const std::shared_ptr<ArrayBuffer>& buffer, double offset, double length) {
103
429
  double size = static_cast<double>(buffer->size());
104
430
  if (!(offset >= 0 && length >= 0 && offset == std::floor(offset) && length == std::floor(length) &&
@@ -16,6 +16,14 @@ class HybridOneCrypto : public HybridOneCryptoSpec {
16
16
  std::string randomUUID() override;
17
17
  std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> digest(
18
18
  const std::string& algorithm, const std::shared_ptr<ArrayBuffer>& buffer, double offset, double length) override;
19
+ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> aesEncrypt(
20
+ const std::shared_ptr<ArrayBuffer>& key, const std::shared_ptr<ArrayBuffer>& iv,
21
+ const std::shared_ptr<ArrayBuffer>& plaintext, const std::optional<std::shared_ptr<ArrayBuffer>>& additionalData,
22
+ double tagLength) override;
23
+ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> aesDecrypt(
24
+ const std::shared_ptr<ArrayBuffer>& key, const std::shared_ptr<ArrayBuffer>& iv,
25
+ const std::shared_ptr<ArrayBuffer>& ciphertext, const std::optional<std::shared_ptr<ArrayBuffer>>& additionalData,
26
+ double tagLength) override;
19
27
  };
20
28
 
21
29
  } // namespace margelo::nitro::one
@@ -27,6 +27,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
  var index_exports = {};
29
29
  __export(index_exports, {
30
+ AESEncryptionKey: () => import_platform.AESEncryptionKey,
31
+ AESSealedData: () => import_platform.AESSealedData,
30
32
  ErrorBoundary: () => import_ErrorBoundary.ErrorBoundary,
31
33
  Head: () => import_head.Head,
32
34
  Link: () => import_Link.Link,
@@ -51,11 +53,11 @@ __export(index_exports, {
51
53
  createApp: () => import_createApp.createApp,
52
54
  createMiddleware: () => import_createMiddleware.createMiddleware,
53
55
  createRoute: () => import_createRoute.createRoute,
54
- getHinge: () => import_platform.getHinge,
56
+ getHinge: () => import_platform2.getHinge,
55
57
  getLinking: () => import_getLinking.getLinking,
56
58
  getLoaderTimingHistory: () => import_useLoader.getLoaderTimingHistory,
57
59
  getServerData: () => import_one_server_only.getServerData,
58
- getSizeClass: () => import_platform.getSizeClass,
60
+ getSizeClass: () => import_platform2.getSizeClass,
59
61
  getURL: () => import_getURL.getURL,
60
62
  handleSkewError: () => import_dynamicImport.handleSkewError,
61
63
  href: () => import_href.href,
@@ -65,7 +67,7 @@ __export(index_exports, {
65
67
  lazyWithRetry: () => import_lazyWithRetry.lazyWithRetry,
66
68
  loadWithRetry: () => import_dynamicImport.loadWithRetry,
67
69
  onClientLoaderResolve: () => import_clientLoaderResolver.onClientLoaderResolve,
68
- onHingeChange: () => import_platform.onHingeChange,
70
+ onHingeChange: () => import_platform2.onHingeChange,
69
71
  redirect: () => import_redirect.redirect,
70
72
  refetchLoader: () => import_useLoader.refetchLoader,
71
73
  registerPreloadedRoute: () => import_useViteRoutes.registerPreloadedRoute,
@@ -78,39 +80,39 @@ __export(index_exports, {
78
80
  setResponseHeaders: () => import_one_server_only.setResponseHeaders,
79
81
  setServerData: () => import_one_server_only.setServerData,
80
82
  useActiveParams: () => import_hooks.useActiveParams,
81
- useAudioPlayer: () => import_platform.useAudioPlayer,
82
- useAudioPlayerStatus: () => import_platform.useAudioPlayerStatus,
83
- useBatteryLevel: () => import_platform.useBatteryLevel,
84
- useBatteryState: () => import_platform.useBatteryState,
83
+ useAudioPlayer: () => import_platform2.useAudioPlayer,
84
+ useAudioPlayerStatus: () => import_platform2.useAudioPlayerStatus,
85
+ useBatteryLevel: () => import_platform2.useBatteryLevel,
86
+ useBatteryState: () => import_platform2.useBatteryState,
85
87
  useBlocker: () => import_useBlocker.useBlocker,
86
- useCalendars: () => import_platform.useCalendars,
88
+ useCalendars: () => import_platform2.useCalendars,
87
89
  useDrawer: () => import_useDrawer.useDrawer,
88
90
  useFocusEffect: () => import_useFocusEffect.useFocusEffect,
89
- useFonts: () => import_platform.useFonts,
91
+ useFonts: () => import_platform2.useFonts,
90
92
  useGlobalSearchParams: () => import_hooks.useGlobalSearchParams,
91
93
  useHeaderHeight: () => import_useHeaderHeight.useHeaderHeight,
92
- useHinge: () => import_platform.useHinge,
94
+ useHinge: () => import_platform2.useHinge,
93
95
  useIsFocused: () => import_core.useIsFocused,
94
- useKeepAwake: () => import_platform.useKeepAwake,
96
+ useKeepAwake: () => import_platform2.useKeepAwake,
95
97
  useLinkTo: () => import_useLinkTo.useLinkTo,
96
98
  useLoader: () => import_useLoader.useLoader,
97
99
  useLoaderState: () => import_useLoader.useLoaderState,
98
100
  useLocalSearchParams: () => import_hooks.useLocalSearchParams,
99
- useLocales: () => import_platform.useLocales,
100
- useLowPowerMode: () => import_platform.useLowPowerMode,
101
+ useLocales: () => import_platform2.useLocales,
102
+ useLowPowerMode: () => import_platform2.useLowPowerMode,
101
103
  useMatch: () => import_useMatches.useMatch,
102
104
  useMatches: () => import_useMatches.useMatches,
103
- useNativeState: () => import_platform.useNativeState,
105
+ useNativeState: () => import_platform2.useNativeState,
104
106
  useNavigation: () => import_useNavigation.useNavigation,
105
107
  useNavigationContainerRef: () => import_hooks.useNavigationContainerRef,
106
- useNetworkState: () => import_platform.useNetworkState,
108
+ useNetworkState: () => import_platform2.useNetworkState,
107
109
  usePageMatch: () => import_useMatches.usePageMatch,
108
110
  useParams: () => import_hooks.useParams,
109
111
  usePathname: () => import_hooks.usePathname,
110
- usePowerState: () => import_platform.usePowerState,
111
- usePreventScreenCapture: () => import_platform.usePreventScreenCapture,
112
- useReservedRegions: () => import_platform.useReservedRegions,
113
- useReservedRegionsReady: () => import_platform.useReservedRegionsReady,
112
+ usePowerState: () => import_platform2.usePowerState,
113
+ usePreventScreenCapture: () => import_platform2.usePreventScreenCapture,
114
+ useReservedRegions: () => import_platform2.useReservedRegions,
115
+ useReservedRegionsReady: () => import_platform2.useReservedRegionsReady,
114
116
  useRootNavigationState: () => import_hooks.useRootNavigationState,
115
117
  useRouter: () => import_hooks.useRouter,
116
118
  useSafeAreaFrame: () => import_safe_area_context.useSafeAreaFrame,
@@ -120,13 +122,13 @@ __export(index_exports, {
120
122
  useSegments: () => import_hooks.useSegments,
121
123
  useServerHeadInsertion: () => import_useServerHeadInsertion.useServerHeadInsertion,
122
124
  useSitemap: () => import_sitemap.useSitemap,
123
- useSizeClass: () => import_platform.useSizeClass,
124
- useSpanning: () => import_platform.useSpanning,
125
+ useSizeClass: () => import_platform2.useSizeClass,
126
+ useSpanning: () => import_platform2.useSpanning,
125
127
  useStack: () => import_useStack.useStack,
126
128
  useTabs: () => import_useTabs.useTabs,
127
129
  useUnstableGlobalHref: () => import_hooks.useUnstableGlobalHref,
128
130
  useValidationState: () => import_router.useValidationState,
129
- useWindowSegments: () => import_platform.useWindowSegments,
131
+ useWindowSegments: () => import_platform2.useWindowSegments,
130
132
  validateParams: () => import_validateParams.validateParams,
131
133
  watchFile: () => import_watchFile.watchFile,
132
134
  withLayoutContext: () => import_withLayoutContext.withLayoutContext,
@@ -136,6 +138,7 @@ module.exports = __toCommonJS(index_exports);
136
138
  var import_createApp = require("./createApp.cjs");
137
139
  var import_one = require("./one.cjs");
138
140
  var import_platform = require("./platform/index.cjs");
141
+ var import_platform2 = require("./platform/index.cjs");
139
142
  var import_core = require("@react-navigation/core");
140
143
  var import_useHeaderHeight = require("./useHeaderHeight.cjs");
141
144
  __reExport(index_exports, require("@vxrn/color-scheme"), module.exports);
@@ -29,6 +29,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
+ AESEncryptionKey: () => import_platform.AESEncryptionKey,
33
+ AESSealedData: () => import_platform.AESSealedData,
32
34
  ErrorBoundary: () => import_ErrorBoundary.ErrorBoundary,
33
35
  Head: () => import_head.Head,
34
36
  Link: () => import_Link.Link,
@@ -53,11 +55,11 @@ __export(index_exports, {
53
55
  createApp: () => import_createApp.createApp,
54
56
  createMiddleware: () => import_createMiddleware.createMiddleware,
55
57
  createRoute: () => import_createRoute.createRoute,
56
- getHinge: () => import_platform.getHinge,
58
+ getHinge: () => import_platform2.getHinge,
57
59
  getLinking: () => import_getLinking.getLinking,
58
60
  getLoaderTimingHistory: () => import_useLoader.getLoaderTimingHistory,
59
61
  getServerData: () => import_one_server_only.getServerData,
60
- getSizeClass: () => import_platform.getSizeClass,
62
+ getSizeClass: () => import_platform2.getSizeClass,
61
63
  getURL: () => import_getURL.getURL,
62
64
  handleSkewError: () => import_dynamicImport.handleSkewError,
63
65
  href: () => import_href.href,
@@ -67,7 +69,7 @@ __export(index_exports, {
67
69
  lazyWithRetry: () => import_lazyWithRetry.lazyWithRetry,
68
70
  loadWithRetry: () => import_dynamicImport.loadWithRetry,
69
71
  onClientLoaderResolve: () => import_clientLoaderResolver.onClientLoaderResolve,
70
- onHingeChange: () => import_platform.onHingeChange,
72
+ onHingeChange: () => import_platform2.onHingeChange,
71
73
  redirect: () => import_redirect.redirect,
72
74
  refetchLoader: () => import_useLoader.refetchLoader,
73
75
  registerPreloadedRoute: () => import_useViteRoutes.registerPreloadedRoute,
@@ -80,39 +82,39 @@ __export(index_exports, {
80
82
  setResponseHeaders: () => import_one_server_only.setResponseHeaders,
81
83
  setServerData: () => import_one_server_only.setServerData,
82
84
  useActiveParams: () => import_hooks.useActiveParams,
83
- useAudioPlayer: () => import_platform.useAudioPlayer,
84
- useAudioPlayerStatus: () => import_platform.useAudioPlayerStatus,
85
- useBatteryLevel: () => import_platform.useBatteryLevel,
86
- useBatteryState: () => import_platform.useBatteryState,
85
+ useAudioPlayer: () => import_platform2.useAudioPlayer,
86
+ useAudioPlayerStatus: () => import_platform2.useAudioPlayerStatus,
87
+ useBatteryLevel: () => import_platform2.useBatteryLevel,
88
+ useBatteryState: () => import_platform2.useBatteryState,
87
89
  useBlocker: () => import_useBlocker.useBlocker,
88
- useCalendars: () => import_platform.useCalendars,
90
+ useCalendars: () => import_platform2.useCalendars,
89
91
  useDrawer: () => import_useDrawer.useDrawer,
90
92
  useFocusEffect: () => import_useFocusEffect.useFocusEffect,
91
- useFonts: () => import_platform.useFonts,
93
+ useFonts: () => import_platform2.useFonts,
92
94
  useGlobalSearchParams: () => import_hooks.useGlobalSearchParams,
93
95
  useHeaderHeight: () => import_useHeaderHeight.useHeaderHeight,
94
- useHinge: () => import_platform.useHinge,
96
+ useHinge: () => import_platform2.useHinge,
95
97
  useIsFocused: () => import_core.useIsFocused,
96
- useKeepAwake: () => import_platform.useKeepAwake,
98
+ useKeepAwake: () => import_platform2.useKeepAwake,
97
99
  useLinkTo: () => import_useLinkTo.useLinkTo,
98
100
  useLoader: () => import_useLoader.useLoader,
99
101
  useLoaderState: () => import_useLoader.useLoaderState,
100
102
  useLocalSearchParams: () => import_hooks.useLocalSearchParams,
101
- useLocales: () => import_platform.useLocales,
102
- useLowPowerMode: () => import_platform.useLowPowerMode,
103
+ useLocales: () => import_platform2.useLocales,
104
+ useLowPowerMode: () => import_platform2.useLowPowerMode,
103
105
  useMatch: () => import_useMatches.useMatch,
104
106
  useMatches: () => import_useMatches.useMatches,
105
- useNativeState: () => import_platform.useNativeState,
107
+ useNativeState: () => import_platform2.useNativeState,
106
108
  useNavigation: () => import_useNavigation.useNavigation,
107
109
  useNavigationContainerRef: () => import_hooks.useNavigationContainerRef,
108
- useNetworkState: () => import_platform.useNetworkState,
110
+ useNetworkState: () => import_platform2.useNetworkState,
109
111
  usePageMatch: () => import_useMatches.usePageMatch,
110
112
  useParams: () => import_hooks.useParams,
111
113
  usePathname: () => import_hooks.usePathname,
112
- usePowerState: () => import_platform.usePowerState,
113
- usePreventScreenCapture: () => import_platform.usePreventScreenCapture,
114
- useReservedRegions: () => import_platform.useReservedRegions,
115
- useReservedRegionsReady: () => import_platform.useReservedRegionsReady,
114
+ usePowerState: () => import_platform2.usePowerState,
115
+ usePreventScreenCapture: () => import_platform2.usePreventScreenCapture,
116
+ useReservedRegions: () => import_platform2.useReservedRegions,
117
+ useReservedRegionsReady: () => import_platform2.useReservedRegionsReady,
116
118
  useRootNavigationState: () => import_hooks.useRootNavigationState,
117
119
  useRouter: () => import_hooks.useRouter,
118
120
  useSafeAreaFrame: () => import_safe_area_context.useSafeAreaFrame,
@@ -122,13 +124,13 @@ __export(index_exports, {
122
124
  useSegments: () => import_hooks.useSegments,
123
125
  useServerHeadInsertion: () => import_useServerHeadInsertion.useServerHeadInsertion,
124
126
  useSitemap: () => import_sitemap.useSitemap,
125
- useSizeClass: () => import_platform.useSizeClass,
126
- useSpanning: () => import_platform.useSpanning,
127
+ useSizeClass: () => import_platform2.useSizeClass,
128
+ useSpanning: () => import_platform2.useSpanning,
127
129
  useStack: () => import_useStack.useStack,
128
130
  useTabs: () => import_useTabs.useTabs,
129
131
  useUnstableGlobalHref: () => import_hooks.useUnstableGlobalHref,
130
132
  useValidationState: () => import_router.useValidationState,
131
- useWindowSegments: () => import_platform.useWindowSegments,
133
+ useWindowSegments: () => import_platform2.useWindowSegments,
132
134
  validateParams: () => import_validateParams.validateParams,
133
135
  watchFile: () => import_watchFile.watchFile,
134
136
  withLayoutContext: () => import_withLayoutContext.withLayoutContext,
@@ -138,6 +140,7 @@ module.exports = __toCommonJS(index_exports);
138
140
  var import_createApp = require("./createApp.native.js");
139
141
  var import_one = require("./one.native.js");
140
142
  var import_platform = require("./platform/index.native.js");
143
+ var import_platform2 = require("./platform/index.native.js");
141
144
  var import_core = require("@react-navigation/core");
142
145
  var import_useHeaderHeight = require("./useHeaderHeight.native.js");
143
146
  __reExport(index_exports, require("@vxrn/color-scheme"), module.exports);