@functionland/fula-client 0.2.24 → 0.2.25

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.
package/fula_js.d.ts CHANGED
@@ -189,6 +189,61 @@ export function putEncrypted(client: EncryptedClient, bucket: string, key: strin
189
189
  */
190
190
  export function putEncryptedWithType(client: EncryptedClient, bucket: string, key: string, data: Uint8Array, content_type: string): Promise<any>;
191
191
 
192
+ /**
193
+ * AES-256-GCM decrypt data with a DEK
194
+ *
195
+ * @param dekBytes - 32-byte DEK
196
+ * @param nonceBase64 - Base64 encoded 12-byte nonce
197
+ * @param ciphertextBase64 - Base64 encoded ciphertext
198
+ * @returns Decrypted plaintext
199
+ */
200
+ export function testAesGcmDecrypt(dek_bytes: Uint8Array, nonce_base64: string, ciphertext_base64: string): Uint8Array;
201
+
202
+ /**
203
+ * AES-256-GCM encrypt data with a DEK
204
+ *
205
+ * @param dekBytes - 32-byte DEK
206
+ * @param plaintext - Data to encrypt
207
+ * @returns JSON string with {nonce, ciphertext} (both base64 encoded)
208
+ */
209
+ export function testAesGcmEncrypt(dek_bytes: Uint8Array, plaintext: Uint8Array): string;
210
+
211
+ /**
212
+ * Full encryption round-trip test
213
+ *
214
+ * This tests the EXACT flow: derive key -> encrypt DEK with HPKE -> encrypt data with AES-GCM
215
+ * then decrypt in reverse order. If this works, the WASM crypto is correct.
216
+ *
217
+ * @param context - Key derivation context (e.g., "fula-files-v1")
218
+ * @param input - Key derivation input (e.g., credentials)
219
+ * @param plaintext - Data to encrypt and decrypt
220
+ * @returns Original plaintext if successful (proves round-trip works)
221
+ */
222
+ export function testFullEncryptionRoundtrip(context: string, input: Uint8Array, plaintext: Uint8Array): Uint8Array;
223
+
224
+ /**
225
+ * Decrypt a wrapped DEK using HPKE with the given secret key
226
+ *
227
+ * This simulates what WebUI WASM should do when decrypting a file.
228
+ *
229
+ * @param secretKeyBytes - 32-byte X25519 secret key
230
+ * @param wrappedDekJson - JSON string from testHpkeEncryptDek
231
+ * @returns 32-byte decrypted DEK
232
+ */
233
+ export function testHpkeDecryptDek(secret_key_bytes: Uint8Array, wrapped_dek_json: string): Uint8Array;
234
+
235
+ /**
236
+ * Encrypt a DEK using HPKE with the given public key
237
+ *
238
+ * This simulates what FxFiles does when encrypting a file.
239
+ * Returns JSON string containing the EncryptedData (wrapped DEK).
240
+ *
241
+ * @param publicKeyBytes - 32-byte X25519 public key
242
+ * @param dekBytes - 32-byte DEK to encrypt
243
+ * @returns JSON string with {version, encapsulated_key, ciphertext}
244
+ */
245
+ export function testHpkeEncryptDek(public_key_bytes: Uint8Array, dek_bytes: Uint8Array): string;
246
+
192
247
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
193
248
 
194
249
  export interface InitOutput {
@@ -217,12 +272,17 @@ export interface InitOutput {
217
272
  readonly listDirectory: (a: number, b: number, c: number, d: number, e: number) => any;
218
273
  readonly putEncrypted: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => any;
219
274
  readonly putEncryptedWithType: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => any;
275
+ readonly testAesGcmDecrypt: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
276
+ readonly testAesGcmEncrypt: (a: number, b: number, c: number, d: number) => [number, number, number, number];
277
+ readonly testFullEncryptionRoundtrip: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
278
+ readonly testHpkeDecryptDek: (a: number, b: number, c: number, d: number) => [number, number, number, number];
279
+ readonly testHpkeEncryptDek: (a: number, b: number, c: number, d: number) => [number, number, number, number];
220
280
  readonly init: () => void;
221
- readonly wasm_bindgen__convert__closures_____invoke__h137a7db9bfc1a698: (a: number, b: number) => void;
222
- readonly wasm_bindgen__closure__destroy__h175e7795724731f3: (a: number, b: number) => void;
223
- readonly wasm_bindgen__convert__closures_____invoke__hfca1d4c99c3f4fb2: (a: number, b: number, c: any) => void;
224
- readonly wasm_bindgen__closure__destroy__hf1f5673d74edd4c1: (a: number, b: number) => void;
225
- readonly wasm_bindgen__convert__closures_____invoke__h480ba7e91e420106: (a: number, b: number, c: any, d: any) => void;
281
+ readonly wasm_bindgen__convert__closures_____invoke__hb49647253b2911c5: (a: number, b: number) => void;
282
+ readonly wasm_bindgen__closure__destroy__hde34fe38f5ae6975: (a: number, b: number) => void;
283
+ readonly wasm_bindgen__convert__closures_____invoke__h7e10992c477d6050: (a: number, b: number, c: any) => void;
284
+ readonly wasm_bindgen__closure__destroy__h40a33609ceb56b6e: (a: number, b: number) => void;
285
+ readonly wasm_bindgen__convert__closures_____invoke__h4b8cebda0a70f497: (a: number, b: number, c: any, d: any) => void;
226
286
  readonly __wbindgen_malloc: (a: number, b: number) => number;
227
287
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
228
288
  readonly __wbindgen_exn_store: (a: number) => void;
package/fula_js.js CHANGED
@@ -227,16 +227,16 @@ if (!('encodeInto' in cachedTextEncoder)) {
227
227
 
228
228
  let WASM_VECTOR_LEN = 0;
229
229
 
230
- function wasm_bindgen__convert__closures_____invoke__h137a7db9bfc1a698(arg0, arg1) {
231
- wasm.wasm_bindgen__convert__closures_____invoke__h137a7db9bfc1a698(arg0, arg1);
230
+ function wasm_bindgen__convert__closures_____invoke__hb49647253b2911c5(arg0, arg1) {
231
+ wasm.wasm_bindgen__convert__closures_____invoke__hb49647253b2911c5(arg0, arg1);
232
232
  }
233
233
 
234
- function wasm_bindgen__convert__closures_____invoke__hfca1d4c99c3f4fb2(arg0, arg1, arg2) {
235
- wasm.wasm_bindgen__convert__closures_____invoke__hfca1d4c99c3f4fb2(arg0, arg1, arg2);
234
+ function wasm_bindgen__convert__closures_____invoke__h7e10992c477d6050(arg0, arg1, arg2) {
235
+ wasm.wasm_bindgen__convert__closures_____invoke__h7e10992c477d6050(arg0, arg1, arg2);
236
236
  }
237
237
 
238
- function wasm_bindgen__convert__closures_____invoke__h480ba7e91e420106(arg0, arg1, arg2, arg3) {
239
- wasm.wasm_bindgen__convert__closures_____invoke__h480ba7e91e420106(arg0, arg1, arg2, arg3);
238
+ function wasm_bindgen__convert__closures_____invoke__h4b8cebda0a70f497(arg0, arg1, arg2, arg3) {
239
+ wasm.wasm_bindgen__convert__closures_____invoke__h4b8cebda0a70f497(arg0, arg1, arg2, arg3);
240
240
  }
241
241
 
242
242
  const __wbindgen_enum_RequestCache = ["default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached"];
@@ -707,6 +707,160 @@ export function putEncryptedWithType(client, bucket, key, data, content_type) {
707
707
  return ret;
708
708
  }
709
709
 
710
+ /**
711
+ * AES-256-GCM decrypt data with a DEK
712
+ *
713
+ * @param dekBytes - 32-byte DEK
714
+ * @param nonceBase64 - Base64 encoded 12-byte nonce
715
+ * @param ciphertextBase64 - Base64 encoded ciphertext
716
+ * @returns Decrypted plaintext
717
+ * @param {Uint8Array} dek_bytes
718
+ * @param {string} nonce_base64
719
+ * @param {string} ciphertext_base64
720
+ * @returns {Uint8Array}
721
+ */
722
+ export function testAesGcmDecrypt(dek_bytes, nonce_base64, ciphertext_base64) {
723
+ const ptr0 = passArray8ToWasm0(dek_bytes, wasm.__wbindgen_malloc);
724
+ const len0 = WASM_VECTOR_LEN;
725
+ const ptr1 = passStringToWasm0(nonce_base64, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
726
+ const len1 = WASM_VECTOR_LEN;
727
+ const ptr2 = passStringToWasm0(ciphertext_base64, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
728
+ const len2 = WASM_VECTOR_LEN;
729
+ const ret = wasm.testAesGcmDecrypt(ptr0, len0, ptr1, len1, ptr2, len2);
730
+ if (ret[3]) {
731
+ throw takeFromExternrefTable0(ret[2]);
732
+ }
733
+ var v4 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
734
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
735
+ return v4;
736
+ }
737
+
738
+ /**
739
+ * AES-256-GCM encrypt data with a DEK
740
+ *
741
+ * @param dekBytes - 32-byte DEK
742
+ * @param plaintext - Data to encrypt
743
+ * @returns JSON string with {nonce, ciphertext} (both base64 encoded)
744
+ * @param {Uint8Array} dek_bytes
745
+ * @param {Uint8Array} plaintext
746
+ * @returns {string}
747
+ */
748
+ export function testAesGcmEncrypt(dek_bytes, plaintext) {
749
+ let deferred4_0;
750
+ let deferred4_1;
751
+ try {
752
+ const ptr0 = passArray8ToWasm0(dek_bytes, wasm.__wbindgen_malloc);
753
+ const len0 = WASM_VECTOR_LEN;
754
+ const ptr1 = passArray8ToWasm0(plaintext, wasm.__wbindgen_malloc);
755
+ const len1 = WASM_VECTOR_LEN;
756
+ const ret = wasm.testAesGcmEncrypt(ptr0, len0, ptr1, len1);
757
+ var ptr3 = ret[0];
758
+ var len3 = ret[1];
759
+ if (ret[3]) {
760
+ ptr3 = 0; len3 = 0;
761
+ throw takeFromExternrefTable0(ret[2]);
762
+ }
763
+ deferred4_0 = ptr3;
764
+ deferred4_1 = len3;
765
+ return getStringFromWasm0(ptr3, len3);
766
+ } finally {
767
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
768
+ }
769
+ }
770
+
771
+ /**
772
+ * Full encryption round-trip test
773
+ *
774
+ * This tests the EXACT flow: derive key -> encrypt DEK with HPKE -> encrypt data with AES-GCM
775
+ * then decrypt in reverse order. If this works, the WASM crypto is correct.
776
+ *
777
+ * @param context - Key derivation context (e.g., "fula-files-v1")
778
+ * @param input - Key derivation input (e.g., credentials)
779
+ * @param plaintext - Data to encrypt and decrypt
780
+ * @returns Original plaintext if successful (proves round-trip works)
781
+ * @param {string} context
782
+ * @param {Uint8Array} input
783
+ * @param {Uint8Array} plaintext
784
+ * @returns {Uint8Array}
785
+ */
786
+ export function testFullEncryptionRoundtrip(context, input, plaintext) {
787
+ const ptr0 = passStringToWasm0(context, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
788
+ const len0 = WASM_VECTOR_LEN;
789
+ const ptr1 = passArray8ToWasm0(input, wasm.__wbindgen_malloc);
790
+ const len1 = WASM_VECTOR_LEN;
791
+ const ptr2 = passArray8ToWasm0(plaintext, wasm.__wbindgen_malloc);
792
+ const len2 = WASM_VECTOR_LEN;
793
+ const ret = wasm.testFullEncryptionRoundtrip(ptr0, len0, ptr1, len1, ptr2, len2);
794
+ if (ret[3]) {
795
+ throw takeFromExternrefTable0(ret[2]);
796
+ }
797
+ var v4 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
798
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
799
+ return v4;
800
+ }
801
+
802
+ /**
803
+ * Decrypt a wrapped DEK using HPKE with the given secret key
804
+ *
805
+ * This simulates what WebUI WASM should do when decrypting a file.
806
+ *
807
+ * @param secretKeyBytes - 32-byte X25519 secret key
808
+ * @param wrappedDekJson - JSON string from testHpkeEncryptDek
809
+ * @returns 32-byte decrypted DEK
810
+ * @param {Uint8Array} secret_key_bytes
811
+ * @param {string} wrapped_dek_json
812
+ * @returns {Uint8Array}
813
+ */
814
+ export function testHpkeDecryptDek(secret_key_bytes, wrapped_dek_json) {
815
+ const ptr0 = passArray8ToWasm0(secret_key_bytes, wasm.__wbindgen_malloc);
816
+ const len0 = WASM_VECTOR_LEN;
817
+ const ptr1 = passStringToWasm0(wrapped_dek_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
818
+ const len1 = WASM_VECTOR_LEN;
819
+ const ret = wasm.testHpkeDecryptDek(ptr0, len0, ptr1, len1);
820
+ if (ret[3]) {
821
+ throw takeFromExternrefTable0(ret[2]);
822
+ }
823
+ var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
824
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
825
+ return v3;
826
+ }
827
+
828
+ /**
829
+ * Encrypt a DEK using HPKE with the given public key
830
+ *
831
+ * This simulates what FxFiles does when encrypting a file.
832
+ * Returns JSON string containing the EncryptedData (wrapped DEK).
833
+ *
834
+ * @param publicKeyBytes - 32-byte X25519 public key
835
+ * @param dekBytes - 32-byte DEK to encrypt
836
+ * @returns JSON string with {version, encapsulated_key, ciphertext}
837
+ * @param {Uint8Array} public_key_bytes
838
+ * @param {Uint8Array} dek_bytes
839
+ * @returns {string}
840
+ */
841
+ export function testHpkeEncryptDek(public_key_bytes, dek_bytes) {
842
+ let deferred4_0;
843
+ let deferred4_1;
844
+ try {
845
+ const ptr0 = passArray8ToWasm0(public_key_bytes, wasm.__wbindgen_malloc);
846
+ const len0 = WASM_VECTOR_LEN;
847
+ const ptr1 = passArray8ToWasm0(dek_bytes, wasm.__wbindgen_malloc);
848
+ const len1 = WASM_VECTOR_LEN;
849
+ const ret = wasm.testHpkeEncryptDek(ptr0, len0, ptr1, len1);
850
+ var ptr3 = ret[0];
851
+ var len3 = ret[1];
852
+ if (ret[3]) {
853
+ ptr3 = 0; len3 = 0;
854
+ throw takeFromExternrefTable0(ret[2]);
855
+ }
856
+ deferred4_0 = ptr3;
857
+ deferred4_1 = len3;
858
+ return getStringFromWasm0(ptr3, len3);
859
+ } finally {
860
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
861
+ }
862
+ }
863
+
710
864
  const EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']);
711
865
 
712
866
  async function __wbg_load(module, imports) {
@@ -1008,7 +1162,7 @@ function __wbg_get_imports() {
1008
1162
  const a = state0.a;
1009
1163
  state0.a = 0;
1010
1164
  try {
1011
- return wasm_bindgen__convert__closures_____invoke__h480ba7e91e420106(a, state0.b, arg0, arg1);
1165
+ return wasm_bindgen__convert__closures_____invoke__h4b8cebda0a70f497(a, state0.b, arg0, arg1);
1012
1166
  } finally {
1013
1167
  state0.a = a;
1014
1168
  }
@@ -1178,6 +1332,11 @@ function __wbg_get_imports() {
1178
1332
  const ret = getStringFromWasm0(arg0, arg1);
1179
1333
  return ret;
1180
1334
  };
1335
+ imports.wbg.__wbindgen_cast_3ef92b33ccb01780 = function(arg0, arg1) {
1336
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 323, function: Function { arguments: [Externref], shim_idx: 324, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1337
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h40a33609ceb56b6e, wasm_bindgen__convert__closures_____invoke__h7e10992c477d6050);
1338
+ return ret;
1339
+ };
1181
1340
  imports.wbg.__wbindgen_cast_4625c577ab2ec9ee = function(arg0) {
1182
1341
  // Cast intrinsic for `U64 -> Externref`.
1183
1342
  const ret = BigInt.asUintN(64, arg0);
@@ -1185,7 +1344,7 @@ function __wbg_get_imports() {
1185
1344
  };
1186
1345
  imports.wbg.__wbindgen_cast_6b8383c0ec1ae211 = function(arg0, arg1) {
1187
1346
  // Cast intrinsic for `Closure(Closure { dtor_idx: 289, function: Function { arguments: [], shim_idx: 290, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1188
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h175e7795724731f3, wasm_bindgen__convert__closures_____invoke__h137a7db9bfc1a698);
1347
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__hde34fe38f5ae6975, wasm_bindgen__convert__closures_____invoke__hb49647253b2911c5);
1189
1348
  return ret;
1190
1349
  };
1191
1350
  imports.wbg.__wbindgen_cast_77bc3e92745e9a35 = function(arg0, arg1) {
@@ -1195,11 +1354,6 @@ function __wbg_get_imports() {
1195
1354
  const ret = v0;
1196
1355
  return ret;
1197
1356
  };
1198
- imports.wbg.__wbindgen_cast_7d99ab386ec3ade6 = function(arg0, arg1) {
1199
- // Cast intrinsic for `Closure(Closure { dtor_idx: 324, function: Function { arguments: [Externref], shim_idx: 325, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1200
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__hf1f5673d74edd4c1, wasm_bindgen__convert__closures_____invoke__hfca1d4c99c3f4fb2);
1201
- return ret;
1202
- };
1203
1357
  imports.wbg.__wbindgen_cast_9ae0607507abb057 = function(arg0) {
1204
1358
  // Cast intrinsic for `I64 -> Externref`.
1205
1359
  const ret = arg0;
package/fula_js_bg.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@functionland/fula-client",
3
- "version": "0.2.24",
3
+ "version": "0.2.25",
4
4
  "type": "module",
5
5
  "description": "JavaScript/TypeScript SDK for Fula decentralized storage - client-side encryption with cross-platform key compatibility",
6
6
  "main": "fula_js.js",