From 46e67d7b0cf04bebe6d04595723ea34a56f692d1 Mon Sep 17 00:00:00 2001 From: John Smith Date: Mon, 15 May 2023 21:20:54 -0400 Subject: [PATCH] wasm work --- Cargo.lock | 3 +- veilid-cli/src/peers_table_view.rs | 2 +- veilid-core/Cargo.toml | 2 +- veilid-core/src/intf/wasm/protected_store.rs | 5 +- veilid-flutter/lib/veilid_config.dart | 202 ++++++ veilid-flutter/lib/veilid_crypto.dart | 4 +- veilid-flutter/lib/veilid_ffi.dart | 336 +++++----- veilid-flutter/lib/veilid_js.dart | 89 --- veilid-flutter/rust/src/dart_ffi.rs | 2 +- veilid-wasm/src/lib.rs | 619 ++++++++++++++++++- 10 files changed, 1016 insertions(+), 248 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db294371..31c87f8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4254,8 +4254,7 @@ dependencies = [ [[package]] name = "range-set-blaze" version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e139f0c5edf89edb65753e67eaf8e6031de21ea59f84cb63e0cfb36aaf80e6d0" +source = "git+https://github.com/crioux/range-set-blaze.git#102c239382a8c79414dcf1257923ac2fe4772342" dependencies = [ "gen_ops", "itertools", diff --git a/veilid-cli/src/peers_table_view.rs b/veilid-cli/src/peers_table_view.rs index e81a7e86..ff328476 100644 --- a/veilid-cli/src/peers_table_view.rs +++ b/veilid-cli/src/peers_table_view.rs @@ -53,7 +53,7 @@ impl TableViewItem for PeerTableData { PeerTableColumn::NodeId => self .node_ids .first() - .cloned() + .map(|n| n.to_string()) .unwrap_or_else(|| "???".to_owned()), PeerTableColumn::Address => self.peer_address.clone(), PeerTableColumn::LatencyAvg => format!( diff --git a/veilid-core/Cargo.toml b/veilid-core/Cargo.toml index 8df5b347..29d0ea05 100644 --- a/veilid-core/Cargo.toml +++ b/veilid-core/Cargo.toml @@ -69,7 +69,7 @@ keyvaluedb = { path = "../external/keyvaluedb/keyvaluedb" } rkyv = { version = "^0", default_features = false, features = ["std", "alloc", "strict", "size_32", "validation"] } data-encoding = { version = "^2" } weak-table = "0.3.2" -range-set-blaze = "0.1.4" +range-set-blaze = { git = "https://github.com/crioux/range-set-blaze.git" } # "0.1.4" xxx replace with git repo # Dependencies for native builds only # Linux, Windows, Mac, iOS, Android diff --git a/veilid-core/src/intf/wasm/protected_store.rs b/veilid-core/src/intf/wasm/protected_store.rs index 842de5ab..126d2b7c 100644 --- a/veilid-core/src/intf/wasm/protected_store.rs +++ b/veilid-core/src/intf/wasm/protected_store.rs @@ -136,7 +136,7 @@ impl ProtectedStore { pub async fn save_user_secret_rkyv(&self, key: K, value: &T) -> EyreResult where K: AsRef + fmt::Debug, - T: RkyvSerialize>, + T: RkyvSerialize, { let v = to_rkyv(value)?; self.save_user_secret(key, &v).await @@ -159,8 +159,7 @@ impl ProtectedStore { T: RkyvArchive, ::Archived: for<'t> CheckBytes>, - ::Archived: - RkyvDeserialize, + ::Archived: RkyvDeserialize, { let out = self.load_user_secret(key).await?; let b = match out { diff --git a/veilid-flutter/lib/veilid_config.dart b/veilid-flutter/lib/veilid_config.dart index 176fe2b3..de814df1 100644 --- a/veilid-flutter/lib/veilid_config.dart +++ b/veilid-flutter/lib/veilid_config.dart @@ -7,6 +7,119 @@ import 'package:change_case/change_case.dart'; import 'veilid_encoding.dart'; import 'veilid.dart'; +////////////////////////////////////////////////////////// +// FFI Platform-specific config + +class VeilidFFIConfigLoggingTerminal { + bool enabled; + VeilidConfigLogLevel level; + + VeilidFFIConfigLoggingTerminal({ + required this.enabled, + required this.level, + }); + + Map toJson() { + return { + 'enabled': enabled, + 'level': level.toJson(), + }; + } + + VeilidFFIConfigLoggingTerminal.fromJson(dynamic json) + : enabled = json['enabled'], + level = veilidConfigLogLevelFromJson(json['level']); +} + +class VeilidFFIConfigLoggingOtlp { + bool enabled; + VeilidConfigLogLevel level; + String grpcEndpoint; + String serviceName; + + VeilidFFIConfigLoggingOtlp({ + required this.enabled, + required this.level, + required this.grpcEndpoint, + required this.serviceName, + }); + + Map toJson() { + return { + 'enabled': enabled, + 'level': level.toJson(), + 'grpc_endpoint': grpcEndpoint, + 'service_name': serviceName, + }; + } + + VeilidFFIConfigLoggingOtlp.fromJson(dynamic json) + : enabled = json['enabled'], + level = veilidConfigLogLevelFromJson(json['level']), + grpcEndpoint = json['grpc_endpoint'], + serviceName = json['service_name']; +} + +class VeilidFFIConfigLoggingApi { + bool enabled; + VeilidConfigLogLevel level; + + VeilidFFIConfigLoggingApi({ + required this.enabled, + required this.level, + }); + + Map toJson() { + return { + 'enabled': enabled, + 'level': level.toJson(), + }; + } + + VeilidFFIConfigLoggingApi.fromJson(dynamic json) + : enabled = json['enabled'], + level = veilidConfigLogLevelFromJson(json['level']); +} + +class VeilidFFIConfigLogging { + VeilidFFIConfigLoggingTerminal terminal; + VeilidFFIConfigLoggingOtlp otlp; + VeilidFFIConfigLoggingApi api; + + VeilidFFIConfigLogging( + {required this.terminal, required this.otlp, required this.api}); + + Map toJson() { + return { + 'terminal': terminal.toJson(), + 'otlp': otlp.toJson(), + 'api': api.toJson(), + }; + } + + VeilidFFIConfigLogging.fromJson(dynamic json) + : terminal = VeilidFFIConfigLoggingTerminal.fromJson(json['terminal']), + otlp = VeilidFFIConfigLoggingOtlp.fromJson(json['otlp']), + api = VeilidFFIConfigLoggingApi.fromJson(json['api']); +} + +class VeilidFFIConfig { + VeilidFFIConfigLogging logging; + + VeilidFFIConfig({ + required this.logging, + }); + + Map toJson() { + return { + 'logging': logging.toJson(), + }; + } + + VeilidFFIConfig.fromJson(Map json) + : logging = VeilidFFIConfigLogging.fromJson(json['logging']); +} + ////////////////////////////////////// /// VeilidConfigLogLevel @@ -29,6 +142,95 @@ VeilidConfigLogLevel veilidConfigLogLevelFromJson(String j) { return VeilidConfigLogLevel.values.byName(j.toCamelCase()); } +////////////////////////////////////////////////////////// +// WASM Platform-specific config + +class VeilidWASMConfigLoggingPerformance { + bool enabled; + VeilidConfigLogLevel level; + bool logsInTimings; + bool logsInConsole; + + VeilidWASMConfigLoggingPerformance({ + required this.enabled, + required this.level, + required this.logsInTimings, + required this.logsInConsole, + }); + + Map toJson() { + return { + 'enabled': enabled, + 'level': level.toJson(), + 'logs_in_timings': logsInTimings, + 'logs_in_console': logsInConsole, + }; + } + + VeilidWASMConfigLoggingPerformance.fromJson(dynamic json) + : enabled = json['enabled'], + level = veilidConfigLogLevelFromJson(json['level']), + logsInTimings = json['logs_in_timings'], + logsInConsole = json['logs_in_console']; +} + +class VeilidWASMConfigLoggingApi { + bool enabled; + VeilidConfigLogLevel level; + + VeilidWASMConfigLoggingApi({ + required this.enabled, + required this.level, + }); + + Map toJson() { + return { + 'enabled': enabled, + 'level': level.toJson(), + }; + } + + VeilidWASMConfigLoggingApi.fromJson(dynamic json) + : enabled = json['enabled'], + level = veilidConfigLogLevelFromJson(json['level']); +} + +class VeilidWASMConfigLogging { + VeilidWASMConfigLoggingPerformance performance; + VeilidWASMConfigLoggingApi api; + + VeilidWASMConfigLogging({required this.performance, required this.api}); + + Map toJson() { + return { + 'performance': performance.toJson(), + 'api': api.toJson(), + }; + } + + VeilidWASMConfigLogging.fromJson(dynamic json) + : performance = + VeilidWASMConfigLoggingPerformance.fromJson(json['performance']), + api = VeilidWASMConfigLoggingApi.fromJson(json['api']); +} + +class VeilidWASMConfig { + VeilidWASMConfigLogging logging; + + VeilidWASMConfig({ + required this.logging, + }); + + Map toJson() { + return { + 'logging': logging.toJson(), + }; + } + + VeilidWASMConfig.fromJson(dynamic json) + : logging = VeilidWASMConfigLogging.fromJson(json['logging']); +} + ////////////////////////////////////// /// VeilidConfig diff --git a/veilid-flutter/lib/veilid_crypto.dart b/veilid-flutter/lib/veilid_crypto.dart index 9f90ed39..f11f0ac9 100644 --- a/veilid-flutter/lib/veilid_crypto.dart +++ b/veilid-flutter/lib/veilid_crypto.dart @@ -145,10 +145,10 @@ abstract class VeilidCryptoSystem { Future randomSharedSecret(); Future generateKeyPair(); Future generateHash(Uint8List data); - Future generateHashReader(Stream> reader); + //Future generateHashReader(Stream> reader); Future validateKeyPair(PublicKey key, SecretKey secret); Future validateHash(Uint8List data, HashDigest hash); - Future validateHashReader(Stream> reader, HashDigest hash); + //Future validateHashReader(Stream> reader, HashDigest hash); Future distance(CryptoKey key1, CryptoKey key2); Future sign(PublicKey key, SecretKey secret, Uint8List data); Future verify(PublicKey key, Uint8List data, Signature signature); diff --git a/veilid-flutter/lib/veilid_ffi.dart b/veilid-flutter/lib/veilid_ffi.dart index 1ad56fa4..4bce79b2 100644 --- a/veilid-flutter/lib/veilid_ffi.dart +++ b/veilid-flutter/lib/veilid_ffi.dart @@ -10,119 +10,6 @@ import 'package:ffi/ffi.dart'; import 'veilid.dart'; import 'veilid_encoding.dart'; -////////////////////////////////////////////////////////// -// FFI Platform-specific config - -class VeilidFFIConfigLoggingTerminal { - bool enabled; - VeilidConfigLogLevel level; - - VeilidFFIConfigLoggingTerminal({ - required this.enabled, - required this.level, - }); - - Map toJson() { - return { - 'enabled': enabled, - 'level': level.toJson(), - }; - } - - VeilidFFIConfigLoggingTerminal.fromJson(dynamic json) - : enabled = json['enabled'], - level = veilidConfigLogLevelFromJson(json['level']); -} - -class VeilidFFIConfigLoggingOtlp { - bool enabled; - VeilidConfigLogLevel level; - String grpcEndpoint; - String serviceName; - - VeilidFFIConfigLoggingOtlp({ - required this.enabled, - required this.level, - required this.grpcEndpoint, - required this.serviceName, - }); - - Map toJson() { - return { - 'enabled': enabled, - 'level': level.toJson(), - 'grpc_endpoint': grpcEndpoint, - 'service_name': serviceName, - }; - } - - VeilidFFIConfigLoggingOtlp.fromJson(dynamic json) - : enabled = json['enabled'], - level = veilidConfigLogLevelFromJson(json['level']), - grpcEndpoint = json['grpc_endpoint'], - serviceName = json['service_name']; -} - -class VeilidFFIConfigLoggingApi { - bool enabled; - VeilidConfigLogLevel level; - - VeilidFFIConfigLoggingApi({ - required this.enabled, - required this.level, - }); - - Map toJson() { - return { - 'enabled': enabled, - 'level': level.toJson(), - }; - } - - VeilidFFIConfigLoggingApi.fromJson(dynamic json) - : enabled = json['enabled'], - level = veilidConfigLogLevelFromJson(json['level']); -} - -class VeilidFFIConfigLogging { - VeilidFFIConfigLoggingTerminal terminal; - VeilidFFIConfigLoggingOtlp otlp; - VeilidFFIConfigLoggingApi api; - - VeilidFFIConfigLogging( - {required this.terminal, required this.otlp, required this.api}); - - Map toJson() { - return { - 'terminal': terminal.toJson(), - 'otlp': otlp.toJson(), - 'api': api.toJson(), - }; - } - - VeilidFFIConfigLogging.fromJson(dynamic json) - : terminal = VeilidFFIConfigLoggingTerminal.fromJson(json['terminal']), - otlp = VeilidFFIConfigLoggingOtlp.fromJson(json['otlp']), - api = VeilidFFIConfigLoggingApi.fromJson(json['api']); -} - -class VeilidFFIConfig { - VeilidFFIConfigLogging logging; - - VeilidFFIConfig({ - required this.logging, - }); - - Map toJson() { - return { - 'logging': logging.toJson(), - }; - } - - VeilidFFIConfig.fromJson(Map json) - : logging = VeilidFFIConfigLogging.fromJson(json['logging']); -} - ////////////////////////////////////////////////////////// // Load the veilid_flutter library once @@ -961,8 +848,9 @@ class VeilidTableDBFFI extends VeilidTableDB { // FFI implementation of VeilidCryptoSystem class VeilidCryptoSystemFFI implements VeilidCryptoSystem { final CryptoKind _kind; + VeilidFFI _ffi; - VeilidCryptoSystemFFI._(this._kind); + VeilidCryptoSystemFFI._(this._ffi, this._kind); @override CryptoKind kind() { @@ -970,42 +858,183 @@ class VeilidCryptoSystemFFI implements VeilidCryptoSystem { } @override - Future cachedDH(PublicKey key, SecretKey secret) {} + Future cachedDH(PublicKey key, SecretKey secret) { + final nativeKey = jsonEncode(key).toNativeUtf8(); + final nativeSecret = jsonEncode(secret).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_cached_dh"); + final sendPort = recvPort.sendPort; + _ffi._cryptoCachedDH(sendPort.nativePort, _kind, nativeKey, nativeSecret); + return processFutureJson(SharedSecret.fromJson, recvPort.first); + } + @override - Future computeDH(PublicKey key, SecretKey secret) {} + Future computeDH(PublicKey key, SecretKey secret) { + final nativeKey = jsonEncode(key).toNativeUtf8(); + final nativeSecret = jsonEncode(secret).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_compute_dh"); + final sendPort = recvPort.sendPort; + _ffi._cryptoComputeDH(sendPort.nativePort, _kind, nativeKey, nativeSecret); + return processFutureJson(SharedSecret.fromJson, recvPort.first); + } + @override - Future randomNonce() {} + Future randomNonce() { + final recvPort = ReceivePort("crypto_random_nonce"); + final sendPort = recvPort.sendPort; + _ffi._cryptoRandomNonce(sendPort.nativePort, _kind); + return processFutureJson(Nonce.fromJson, recvPort.first); + } + @override - Future randomSharedSecret() {} + Future randomSharedSecret() { + final recvPort = ReceivePort("crypto_random_shared_secret"); + final sendPort = recvPort.sendPort; + _ffi._cryptoRandomSharedSecret(sendPort.nativePort, _kind); + return processFutureJson(SharedSecret.fromJson, recvPort.first); + } + @override - Future generateKeyPair() {} + Future generateKeyPair() { + final recvPort = ReceivePort("crypto_generate_key_pair"); + final sendPort = recvPort.sendPort; + _ffi._cryptoGenerateKeyPair(sendPort.nativePort, _kind); + return processFutureJson(KeyPair.fromJson, recvPort.first); + } + @override - Future generateHash(Uint8List data) {} + Future generateHash(Uint8List data) { + final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_generate_hash"); + final sendPort = recvPort.sendPort; + _ffi._cryptoGenerateHash(sendPort.nativePort, _kind, nativeEncodedData); + return processFutureJson(HashDigest.fromJson, recvPort.first); + } + @override - Future generateHashReader(Stream> reader) {} + Future validateKeyPair(PublicKey key, SecretKey secret) { + final nativeKey = jsonEncode(key).toNativeUtf8(); + final nativeSecret = jsonEncode(secret).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_validate_key_pair"); + final sendPort = recvPort.sendPort; + _ffi._cryptoValidateKeyPair( + sendPort.nativePort, _kind, nativeKey, nativeSecret); + return processFuturePlain(recvPort.first); + } + @override - Future validateKeyPair(PublicKey key, SecretKey secret) {} + Future validateHash(Uint8List data, HashDigest hash) { + final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); + final nativeHash = jsonEncode(hash).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_validate_hash"); + final sendPort = recvPort.sendPort; + _ffi._cryptoValidateHash( + sendPort.nativePort, _kind, nativeEncodedData, nativeHash); + return processFuturePlain(recvPort.first); + } + @override - Future validateHash(Uint8List data, HashDigest hash) {} + Future distance(CryptoKey key1, CryptoKey key2) { + final nativeKey1 = jsonEncode(key1).toNativeUtf8(); + final nativeKey2 = jsonEncode(key2).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_distance"); + final sendPort = recvPort.sendPort; + _ffi._cryptoDistance(sendPort.nativePort, _kind, nativeKey1, nativeKey2); + return processFutureJson(CryptoKeyDistance.fromJson, recvPort.first); + } + @override - Future validateHashReader(Stream> reader, HashDigest hash) {} + Future sign(PublicKey key, SecretKey secret, Uint8List data) { + final nativeKey = jsonEncode(key).toNativeUtf8(); + final nativeSecret = jsonEncode(secret).toNativeUtf8(); + final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_sign"); + final sendPort = recvPort.sendPort; + _ffi._cryptoSign( + sendPort.nativePort, _kind, nativeKey, nativeSecret, nativeEncodedData); + return processFutureJson(Signature.fromJson, recvPort.first); + } + @override - Future distance(CryptoKey key1, CryptoKey key2) {} + Future verify(PublicKey key, Uint8List data, Signature signature) { + final nativeKey = jsonEncode(key).toNativeUtf8(); + final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); + final nativeSignature = jsonEncode(signature).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_sign"); + final sendPort = recvPort.sendPort; + _ffi._cryptoSign(sendPort.nativePort, _kind, nativeKey, nativeEncodedData, + nativeSignature); + return processFutureVoid(recvPort.first); + } + @override - Future sign(PublicKey key, SecretKey secret, Uint8List data) {} - @override - Future verify(PublicKey key, Uint8List data, Signature signature) {} - @override - Future aeadOverhead() {} + Future aeadOverhead() { + final recvPort = ReceivePort("crypto_aead_overhead"); + final sendPort = recvPort.sendPort; + _ffi._cryptoAeadOverhead( + sendPort.nativePort, + _kind, + ); + return processFuturePlain(recvPort.first); + } + @override Future decryptAead(Uint8List body, Nonce nonce, - SharedSecret sharedSecret, Uint8List? associatedData) {} + SharedSecret sharedSecret, Uint8List? associatedData) async { + final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8(); + final nativeNonce = jsonEncode(nonce).toNativeUtf8(); + final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8(); + final nativeSignature = (associatedData != null) + ? jsonEncode(associatedData).toNativeUtf8() + : nullptr; + + final recvPort = ReceivePort("crypto_decrypt_aead"); + final sendPort = recvPort.sendPort; + _ffi._cryptoDecryptAead(sendPort.nativePort, _kind, nativeEncodedBody, + nativeNonce, nativeSharedSecret, nativeSignature); + final out = await processFuturePlain(recvPort.first); + return base64UrlNoPadDecode(out); + } + @override Future encryptAead(Uint8List body, Nonce nonce, - SharedSecret sharedSecret, Uint8List? associatedData) {} + SharedSecret sharedSecret, Uint8List? associatedData) async { + final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8(); + final nativeNonce = jsonEncode(nonce).toNativeUtf8(); + final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8(); + final nativeSignature = (associatedData != null) + ? jsonEncode(associatedData).toNativeUtf8() + : nullptr; + + final recvPort = ReceivePort("crypto_encrypt_aead"); + final sendPort = recvPort.sendPort; + _ffi._cryptoEncryptAead(sendPort.nativePort, _kind, nativeEncodedBody, + nativeNonce, nativeSharedSecret, nativeSignature); + final out = await processFuturePlain(recvPort.first); + return base64UrlNoPadDecode(out); + } + @override Future cryptNoAuth( - Uint8List body, Nonce nonce, SharedSecret sharedSecret) {} + Uint8List body, Nonce nonce, SharedSecret sharedSecret) async { + final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8(); + final nativeNonce = jsonEncode(nonce).toNativeUtf8(); + final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8(); + + final recvPort = ReceivePort("crypto_crypt_no_auth"); + final sendPort = recvPort.sendPort; + _ffi._cryptoCryptNoAuth(sendPort.nativePort, _kind, nativeEncodedBody, + nativeNonce, nativeSharedSecret); + final out = await processFuturePlain(recvPort.first); + return base64UrlNoPadDecode(out); + } } // FFI implementation of high level Veilid API @@ -1363,16 +1392,15 @@ class VeilidFFI implements Veilid { @override Future newCustomPrivateRoute( - Stability stability, Sequencing sequencing) async { + Stability stability, Sequencing sequencing) { final recvPort = ReceivePort("new_custom_private_route"); final sendPort = recvPort.sendPort; _newCustomPrivateRoute( sendPort.nativePort, jsonEncode(stability).toNativeUtf8(), jsonEncode(sequencing).toNativeUtf8()); - final routeBlob = - await processFutureJson(RouteBlob.fromJson, recvPort.first); - return routeBlob; + + return processFutureJson(RouteBlob.fromJson, recvPort.first); } @override @@ -1436,12 +1464,12 @@ class VeilidFFI implements Veilid { if (!validCryptoKinds().contains(kind)) { throw VeilidAPIExceptionGeneric("unsupported cryptosystem"); } - return VeilidCryptoSystemFFI._(kind); + return VeilidCryptoSystemFFI._(this, kind); } @override Future bestCryptoSystem() async { - return VeilidCryptoSystemFFI._(_bestCryptoKind()); + return VeilidCryptoSystemFFI._(this, _bestCryptoKind()); } @override @@ -1451,19 +1479,41 @@ class VeilidFFI implements Veilid { final nativeData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeSignatures = jsonEncode(signatures).toNativeUtf8(); - final recvPort = ReceivePort("app_call_reply"); + final recvPort = ReceivePort("verify_signatures"); final sendPort = recvPort.sendPort; _verifySignatures( sendPort.nativePort, nativeNodeIds, nativeData, nativeSignatures); return processFutureJson( jsonListConstructor(TypedKey.fromJson), recvPort.first); } -xxx + @override Future> generateSignatures( - Uint8List data, List keyPairs) {} + Uint8List data, List keyPairs) { + final nativeData = base64UrlNoPadEncode(data).toNativeUtf8(); + final nativeKeyPairs = jsonEncode(keyPairs).toNativeUtf8(); + + final recvPort = ReceivePort("generate_signatures"); + final sendPort = recvPort.sendPort; + _generateSignatures(sendPort.nativePort, nativeData, nativeKeyPairs); + return processFutureJson( + jsonListConstructor(TypedSignature.fromJson), + recvPort.first); + } + @override - Future generateKeyPair(CryptoKind kind) {} + Timestamp now() { + final ts = _now(); + return Timestamp(value: BigInt.from(ts)); + } + + @override + Future generateKeyPair(CryptoKind kind) { + final recvPort = ReceivePort("generate_key_pair"); + final sendPort = recvPort.sendPort; + _generateKeyPair(sendPort.nativePort, kind); + return processFutureJson(TypedKeyPair.fromJson, recvPort.first); + } @override Future debug(String command) async { diff --git a/veilid-flutter/lib/veilid_js.dart b/veilid-flutter/lib/veilid_js.dart index 3cc9efc1..a46eefa5 100644 --- a/veilid-flutter/lib/veilid_js.dart +++ b/veilid-flutter/lib/veilid_js.dart @@ -9,95 +9,6 @@ import 'dart:typed_data'; import 'veilid_encoding.dart'; -////////////////////////////////////////////////////////// -// WASM Platform-specific config - -class VeilidWASMConfigLoggingPerformance { - bool enabled; - VeilidConfigLogLevel level; - bool logsInTimings; - bool logsInConsole; - - VeilidWASMConfigLoggingPerformance({ - required this.enabled, - required this.level, - required this.logsInTimings, - required this.logsInConsole, - }); - - Map toJson() { - return { - 'enabled': enabled, - 'level': level.toJson(), - 'logs_in_timings': logsInTimings, - 'logs_in_console': logsInConsole, - }; - } - - VeilidWASMConfigLoggingPerformance.fromJson(dynamic json) - : enabled = json['enabled'], - level = veilidConfigLogLevelFromJson(json['level']), - logsInTimings = json['logs_in_timings'], - logsInConsole = json['logs_in_console']; -} - -class VeilidWASMConfigLoggingApi { - bool enabled; - VeilidConfigLogLevel level; - - VeilidWASMConfigLoggingApi({ - required this.enabled, - required this.level, - }); - - Map toJson() { - return { - 'enabled': enabled, - 'level': level.toJson(), - }; - } - - VeilidWASMConfigLoggingApi.fromJson(dynamic json) - : enabled = json['enabled'], - level = veilidConfigLogLevelFromJson(json['level']); -} - -class VeilidWASMConfigLogging { - VeilidWASMConfigLoggingPerformance performance; - VeilidWASMConfigLoggingApi api; - - VeilidWASMConfigLogging({required this.performance, required this.api}); - - Map toJson() { - return { - 'performance': performance.toJson(), - 'api': api.toJson(), - }; - } - - VeilidWASMConfigLogging.fromJson(dynamic json) - : performance = - VeilidWASMConfigLoggingPerformance.fromJson(json['performance']), - api = VeilidWASMConfigLoggingApi.fromJson(json['api']); -} - -class VeilidWASMConfig { - VeilidWASMConfigLogging logging; - - VeilidWASMConfig({ - required this.logging, - }); - - Map toJson() { - return { - 'logging': logging.toJson(), - }; - } - - VeilidWASMConfig.fromJson(dynamic json) - : logging = VeilidWASMConfigLogging.fromJson(json['logging']); -} - ////////////////////////////////////////////////////////// Veilid getVeilid() => VeilidJS(); diff --git a/veilid-flutter/rust/src/dart_ffi.rs b/veilid-flutter/rust/src/dart_ffi.rs index cd44552d..8294ea19 100644 --- a/veilid-flutter/rust/src/dart_ffi.rs +++ b/veilid-flutter/rust/src/dart_ffi.rs @@ -615,7 +615,7 @@ pub extern "C" fn routing_context_watch_dht_values(port: i64, id: u32, key: FfiS let routing_context = { let rc = ROUTING_CONTEXTS.lock(); let Some(routing_context) = rc.get(&id) else { - return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_set_dht_value", "id", id)); + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_watch_dht_values", "id", id)); }; routing_context.clone() }; diff --git a/veilid-wasm/src/lib.rs b/veilid-wasm/src/lib.rs index 82295e08..aa09a491 100644 --- a/veilid-wasm/src/lib.rs +++ b/veilid-wasm/src/lib.rs @@ -375,9 +375,6 @@ pub fn routing_context_app_call(id: u32, target: String, request: String) -> Pro .decode(request.as_bytes()) .unwrap(); wrap_api_future_plain(async move { - let veilid_api = get_veilid_api()?; - let routing_table = veilid_api.routing_table()?; - let routing_context = { let rc = (*ROUTING_CONTEXTS).borrow(); let Some(routing_context) = rc.get(&id) else { @@ -399,9 +396,6 @@ pub fn routing_context_app_message(id: u32, target: String, message: String) -> .decode(message.as_bytes()) .unwrap(); wrap_api_future_void(async move { - let veilid_api = get_veilid_api()?; - let routing_table = veilid_api.routing_table()?; - let routing_context = { let rc = (*ROUTING_CONTEXTS).borrow(); let Some(routing_context) = rc.get(&id) else { @@ -416,6 +410,167 @@ pub fn routing_context_app_message(id: u32, target: String, message: String) -> }) } +#[wasm_bindgen()] +pub fn routing_context_create_dht_record(id: u32, kind: u32, schema: String) -> Promise { + let crypto_kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + let schema: veilid_core::DHTSchema = veilid_core::deserialize_json(&schema).unwrap(); + + wrap_api_future_json(async move { + let routing_context = { + let rc = (*ROUTING_CONTEXTS).borrow(); + let Some(routing_context) = rc.get(&id) else { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_create_dht_record", "id", id)); + }; + routing_context.clone() + }; + + let dht_record_descriptor = routing_context + .create_dht_record(crypto_kind, schema) + .await?; + APIResult::Ok(dht_record_descriptor) + }) +} + +#[wasm_bindgen()] +pub fn routing_context_open_dht_record(id: u32, key: String, writer: Option) -> Promise { + let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap(); + let writer: Option = + writer.map(|s| veilid_core::deserialize_json(&s).unwrap()); + wrap_api_future_json(async move { + let routing_context = { + let rc = (*ROUTING_CONTEXTS).borrow(); + let Some(routing_context) = rc.get(&id) else { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_open_dht_record", "id", id)); + }; + routing_context.clone() + }; + let dht_record_descriptor = routing_context.open_dht_record(key, writer).await?; + APIResult::Ok(dht_record_descriptor) + }) +} + +#[wasm_bindgen()] +pub fn routing_context_close_dht_record(id: u32, key: String) -> Promise { + let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap(); + wrap_api_future_void(async move { + let routing_context = { + let rc = (*ROUTING_CONTEXTS).borrow(); + let Some(routing_context) = rc.get(&id) else { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_close_dht_record", "id", id)); + }; + routing_context.clone() + }; + routing_context.close_dht_record(key).await?; + APIRESULT_UNDEFINED + }) +} + +#[wasm_bindgen()] +pub fn routing_context_delete_dht_record(id: u32, key: String) -> Promise { + let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap(); + wrap_api_future_void(async move { + let routing_context = { + let rc = (*ROUTING_CONTEXTS).borrow(); + let Some(routing_context) = rc.get(&id) else { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_delete_dht_record", "id", id)); + }; + routing_context.clone() + }; + routing_context.delete_dht_record(key).await?; + APIRESULT_UNDEFINED + }) +} + +#[wasm_bindgen()] +pub fn routing_context_get_dht_value( + id: u32, + key: String, + subkey: u32, + force_refresh: bool, +) -> Promise { + let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap(); + wrap_api_future_json(async move { + let routing_context = { + let rc = (*ROUTING_CONTEXTS).borrow(); + let Some(routing_context) = rc.get(&id) else { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_get_dht_value", "id", id)); + }; + routing_context.clone() + }; + let res = routing_context + .get_dht_value(key, subkey, force_refresh) + .await?; + APIResult::Ok(res) + }) +} + +#[wasm_bindgen()] +pub fn routing_context_set_dht_value(id: u32, key: String, subkey: u32, data: String) -> Promise { + let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap(); + let data: Vec = data_encoding::BASE64URL_NOPAD + .decode(&data.as_bytes()) + .unwrap(); + + wrap_api_future_json(async move { + let routing_context = { + let rc = (*ROUTING_CONTEXTS).borrow(); + let Some(routing_context) = rc.get(&id) else { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_set_dht_value", "id", id)); + }; + routing_context.clone() + }; + let res = routing_context.set_dht_value(key, subkey, data).await?; + APIResult::Ok(res) + }) +} + +#[wasm_bindgen()] +pub fn routing_context_watch_dht_values( + id: u32, + key: String, + subkeys: String, + expiration: String, + count: u32, +) -> Promise { + let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap(); + let subkeys: veilid_core::ValueSubkeyRangeSet = + veilid_core::deserialize_json(&subkeys).unwrap(); + let expiration = veilid_core::Timestamp::from_str(&expiration).unwrap(); + + wrap_api_future_plain(async move { + let routing_context = { + let rc = (*ROUTING_CONTEXTS).borrow(); + let Some(routing_context) = rc.get(&id) else { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_watch_dht_values", "id", id)); + }; + routing_context.clone() + }; + let res = routing_context + .watch_dht_values(key, subkeys, expiration, count) + .await?; + APIResult::Ok(res.to_string()) + }) +} + +#[wasm_bindgen()] +pub fn routing_context_cancel_dht_watch(id: u32, key: String, subkeys: String) -> Promise { + let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap(); + let subkeys: veilid_core::ValueSubkeyRangeSet = + veilid_core::deserialize_json(&subkeys).unwrap(); + + wrap_api_future_plain(async move { + let routing_context = { + let rc = (*ROUTING_CONTEXTS).borrow(); + let Some(routing_context) = rc.get(&id) else { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_cancel_dht_watch", "id", id)); + }; + routing_context.clone() + }; + let res = routing_context.cancel_dht_watch(key, subkeys).await?; + APIResult::Ok(res) + }) +} + #[wasm_bindgen()] pub fn new_private_route() -> Promise { wrap_api_future_json(async move { @@ -738,6 +893,458 @@ pub fn table_db_delete(id: u32, col: u32, key: String) -> Promise { }) } +#[wasm_bindgen()] +pub fn valid_crypto_kinds() -> String { + veilid_core::serialize_json( + veilid_core::VALID_CRYPTO_KINDS + .iter() + .map(|k| (*k).into()) + .collect::>(), + ) +} + +#[wasm_bindgen()] +pub fn best_crypto_kind() -> u32 { + veilid_core::best_crypto_kind().into() +} + +#[wasm_bindgen()] +pub fn verify_signatures(node_ids: String, data: String, signatures: String) -> Promise { + let node_ids: Vec = veilid_core::deserialize_json(&node_ids).unwrap(); + + let data: Vec = data_encoding::BASE64URL_NOPAD + .decode(data.as_bytes()) + .unwrap(); + + let typed_signatures: Vec = + veilid_core::deserialize_json(&signatures).unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let out = crypto.verify_signatures(&node_ids, &data, &typed_signatures)?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn generate_signatures(data: String, key_pairs: String) -> Promise { + let data: Vec = data_encoding::BASE64URL_NOPAD + .decode(data.as_bytes()) + .unwrap(); + + let key_pairs: Vec = + veilid_core::deserialize_json(&key_pairs).unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let out = crypto.generate_signatures(&data, &key_pairs, |k, s| { + veilid_core::TypedSignature::new(k.kind, s) + })?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn generate_key_pair(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + wrap_api_future_json(async move { + let out = veilid_core::Crypto::generate_keypair(kind)?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_cached_dh(kind: u32, key: String, secret: String) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let key: veilid_core::PublicKey = veilid_core::deserialize_json(&key).unwrap(); + let secret: veilid_core::SecretKey = veilid_core::deserialize_json(&secret).unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_cached_dh", + "kind", + kind.to_string(), + ) + })?; + let out = csv.cached_dh(&key, &secret)?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_compute_dh(kind: u32, key: String, secret: String) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let key: veilid_core::PublicKey = veilid_core::deserialize_json(&key).unwrap(); + let secret: veilid_core::SecretKey = veilid_core::deserialize_json(&secret).unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_compute_dh", + "kind", + kind.to_string(), + ) + })?; + let out = csv.compute_dh(&key, &secret)?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_random_nonce(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_random_nonce", + "kind", + kind.to_string(), + ) + })?; + let out = csv.random_nonce(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_random_shared_secret(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_random_shared_secret", + "kind", + kind.to_string(), + ) + })?; + let out = csv.random_shared_secret(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_generate_key_pair(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_generate_key_pair", + "kind", + kind.to_string(), + ) + })?; + let out = csv.generate_keypair(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_generate_hash(kind: u32, data: String) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let data: Vec = data_encoding::BASE64URL_NOPAD + .decode(data.as_bytes()) + .unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_generate_hash", + "kind", + kind.to_string(), + ) + })?; + let out = csv.generate_hash(&data); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_validate_key_pair(kind: u32, key: String, secret: String) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let key: veilid_core::PublicKey = veilid_core::deserialize_json(&key).unwrap(); + let secret: veilid_core::SecretKey = veilid_core::deserialize_json(&secret).unwrap(); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_validate_key_pair", + "kind", + kind.to_string(), + ) + })?; + let out = csv.validate_keypair(&key, &secret); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_validate_hash(kind: u32, data: String, hash: String) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let data: Vec = data_encoding::BASE64URL_NOPAD + .decode(data.as_bytes()) + .unwrap(); + + let hash: veilid_core::HashDigest = veilid_core::deserialize_json(&hash).unwrap(); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_validate_hash", + "kind", + kind.to_string(), + ) + })?; + let out = csv.validate_hash(&data, &hash); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_distance(kind: u32, key1: String, key2: String) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let key1: veilid_core::CryptoKey = veilid_core::deserialize_json(&key1).unwrap(); + let key2: veilid_core::CryptoKey = veilid_core::deserialize_json(&key2).unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_distance", + "kind", + kind.to_string(), + ) + })?; + let out = csv.distance(&key1, &key2); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_sign(kind: u32, key: String, secret: String, data: String) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let key: veilid_core::CryptoKey = veilid_core::deserialize_json(&key).unwrap(); + let secret: veilid_core::CryptoKey = veilid_core::deserialize_json(&secret).unwrap(); + + let data: Vec = data_encoding::BASE64URL_NOPAD + .decode(data.as_bytes()) + .unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument("crypto_sign", "kind", kind.to_string()) + })?; + let out = csv.sign(&key, &secret, &data)?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_verify(kind: u32, key: String, data: String, signature: String) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let key: veilid_core::CryptoKey = veilid_core::deserialize_json(&key).unwrap(); + let data: Vec = data_encoding::BASE64URL_NOPAD + .decode(data.as_bytes()) + .unwrap(); + let signature: veilid_core::Signature = veilid_core::deserialize_json(&signature).unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument("crypto_verify", "kind", kind.to_string()) + })?; + let out = csv.verify(&key, &data, &signature)?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_aead_overhead(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_aead_overhead", + "kind", + kind.to_string(), + ) + })?; + let out = csv.aead_overhead(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_decrypt_aead( + kind: u32, + body: String, + nonce: String, + shared_secret: String, + associated_data: Option, +) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let body: Vec = data_encoding::BASE64URL_NOPAD + .decode(body.as_bytes()) + .unwrap(); + + let nonce: veilid_core::Nonce = veilid_core::deserialize_json(&nonce).unwrap(); + + let shared_secret: veilid_core::SharedSecret = + veilid_core::deserialize_json(&shared_secret).unwrap(); + + let associated_data: Option> = associated_data.map(|ad| { + data_encoding::BASE64URL_NOPAD + .decode(ad.as_bytes()) + .unwrap() + }); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_decrypt_aead", + "kind", + kind.to_string(), + ) + })?; + let out = csv.decrypt_aead( + &body, + &nonce, + &shared_secret, + match &associated_data { + Some(ad) => Some(ad.as_slice()), + None => None, + }, + )?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_encrypt_aead( + kind: u32, + body: String, + nonce: String, + shared_secret: String, + associated_data: Option, +) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let body: Vec = data_encoding::BASE64URL_NOPAD + .decode(body.as_bytes()) + .unwrap(); + + let nonce: veilid_core::Nonce = veilid_core::deserialize_json(&nonce).unwrap(); + + let shared_secret: veilid_core::SharedSecret = + veilid_core::deserialize_json(&shared_secret).unwrap(); + + let associated_data: Option> = associated_data.map(|ad| { + data_encoding::BASE64URL_NOPAD + .decode(ad.as_bytes()) + .unwrap() + }); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_encrypt_aead", + "kind", + kind.to_string(), + ) + })?; + let out = csv.encrypt_aead( + &body, + &nonce, + &shared_secret, + match &associated_data { + Some(ad) => Some(ad.as_slice()), + None => None, + }, + )?; + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_crypt_no_auth( + kind: u32, + body: String, + nonce: String, + shared_secret: String, +) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind); + + let mut body: Vec = data_encoding::BASE64URL_NOPAD + .decode(body.as_bytes()) + .unwrap(); + + let nonce: veilid_core::Nonce = veilid_core::deserialize_json(&nonce).unwrap(); + + let shared_secret: veilid_core::SharedSecret = + veilid_core::deserialize_json(&shared_secret).unwrap(); + + wrap_api_future_json(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_crypt_no_auth", + "kind", + kind.to_string(), + ) + })?; + csv.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret); + APIResult::Ok(body) + }) +} + +#[wasm_bindgen()] +pub fn now() -> u64 { + veilid_core::get_aligned_timestamp().as_u64() +} + #[wasm_bindgen()] pub fn debug(command: String) -> Promise { wrap_api_future_plain(async move {