ping-openmls-sdk-react-native-macos 0.3.0 → 0.6.0
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/Frameworks/libping_ffi.a +0 -0
- package/ios/Generated.swift +3 -3
- package/ios/PingNativeModule.m +4 -0
- package/ios/PingNativeModule.swift +22 -2
- package/ios/pingFFI.h +1 -1
- package/package.json +1 -1
- package/src/MessagingClient.ts +23 -0
- package/src/NativePing.ts +5 -0
package/Frameworks/libping_ffi.a
CHANGED
|
Binary file
|
package/ios/Generated.swift
CHANGED
|
@@ -814,11 +814,11 @@ open class MessagingClient:
|
|
|
814
814
|
try! rustCall { uniffi_ping_ffi_fn_free_messagingclient(pointer, $0) }
|
|
815
815
|
}
|
|
816
816
|
|
|
817
|
-
public static func `init`(identityExport: Data, deviceLabel: String, storage: Storage, transport: Transport, nowMs: UInt64, sqlitePath: String?, sqliteEncryptionKey: Data?) async throws -> MessagingClient {
|
|
817
|
+
public static func `init`(identityExport: Data, deviceLabel: String, storage: Storage, transport: Transport, nowMs: UInt64, sqlitePath: String?, sqliteEncryptionKey: Data?, deviceSigningSecretKey: Data?) async throws -> MessagingClient {
|
|
818
818
|
return
|
|
819
819
|
try await uniffiRustCallAsync(
|
|
820
820
|
rustFutureFunc: {
|
|
821
|
-
uniffi_ping_ffi_fn_constructor_messagingclient_init(FfiConverterData.lower(identityExport), FfiConverterString.lower(deviceLabel), FfiConverterTypeStorage.lower(storage), FfiConverterTypeTransport.lower(transport), FfiConverterUInt64.lower(nowMs), FfiConverterOptionString.lower(sqlitePath), FfiConverterOptionData.lower(sqliteEncryptionKey))
|
|
821
|
+
uniffi_ping_ffi_fn_constructor_messagingclient_init(FfiConverterData.lower(identityExport), FfiConverterString.lower(deviceLabel), FfiConverterTypeStorage.lower(storage), FfiConverterTypeTransport.lower(transport), FfiConverterUInt64.lower(nowMs), FfiConverterOptionString.lower(sqlitePath), FfiConverterOptionData.lower(sqliteEncryptionKey), FfiConverterOptionData.lower(deviceSigningSecretKey))
|
|
822
822
|
},
|
|
823
823
|
pollFunc: ffi_ping_ffi_rust_future_poll_pointer,
|
|
824
824
|
completeFunc: ffi_ping_ffi_rust_future_complete_pointer,
|
|
@@ -3610,7 +3610,7 @@ private var initializationResult: InitializationResult = {
|
|
|
3610
3610
|
if uniffi_ping_ffi_checksum_method_transport_send() != 46493 {
|
|
3611
3611
|
return InitializationResult.apiChecksumMismatch
|
|
3612
3612
|
}
|
|
3613
|
-
if uniffi_ping_ffi_checksum_constructor_messagingclient_init() !=
|
|
3613
|
+
if uniffi_ping_ffi_checksum_constructor_messagingclient_init() != 35443 {
|
|
3614
3614
|
return InitializationResult.apiChecksumMismatch
|
|
3615
3615
|
}
|
|
3616
3616
|
|
package/ios/PingNativeModule.m
CHANGED
|
@@ -51,11 +51,15 @@ RCT_EXTERN_METHOD(generateIdentityExport: (RCTPromiseResolveBlock)resolve
|
|
|
51
51
|
// Stage 4b: MessagingClient lifecycle.
|
|
52
52
|
// [CR-4] sqlitePath + sqliteEncryptionKeyB64 are optional (nullable) — passing nil for
|
|
53
53
|
// path falls back to the in-memory provider.
|
|
54
|
+
// `deviceSigningSecretKeyB64` is the optional 32-byte Ed25519 secret the SDK adopts
|
|
55
|
+
// as its device signing key on first init — used to align device_id with the host
|
|
56
|
+
// auth layer's JWT claim. Pass nil to keep the random-key default.
|
|
54
57
|
RCT_EXTERN_METHOD(initClient: (NSString *)identityB64
|
|
55
58
|
deviceLabel: (NSString *)deviceLabel
|
|
56
59
|
nowMs: (double)nowMs
|
|
57
60
|
sqlitePath: (NSString *)sqlitePath
|
|
58
61
|
sqliteEncryptionKeyB64: (NSString *)sqliteEncryptionKeyB64
|
|
62
|
+
deviceSigningSecretKeyB64: (NSString *)deviceSigningSecretKeyB64
|
|
59
63
|
resolver: (RCTPromiseResolveBlock)resolve
|
|
60
64
|
rejecter: (RCTPromiseRejectBlock)reject)
|
|
61
65
|
|
|
@@ -211,13 +211,14 @@ public final class PingNative: RCTEventEmitter {
|
|
|
211
211
|
/// `nowMs` is the wall-clock at the call site (Hermes can't pass UInt64 across the
|
|
212
212
|
/// bridge precisely so we accept Double and truncate; valid for the next ~285,000
|
|
213
213
|
/// years of Unix time).
|
|
214
|
-
@objc(initClient:deviceLabel:nowMs:sqlitePath:sqliteEncryptionKeyB64:resolver:rejecter:)
|
|
214
|
+
@objc(initClient:deviceLabel:nowMs:sqlitePath:sqliteEncryptionKeyB64:deviceSigningSecretKeyB64:resolver:rejecter:)
|
|
215
215
|
public func initClient(
|
|
216
216
|
_ identityB64: String,
|
|
217
217
|
deviceLabel: String,
|
|
218
218
|
nowMs: Double,
|
|
219
219
|
sqlitePath: String?,
|
|
220
220
|
sqliteEncryptionKeyB64: String?,
|
|
221
|
+
deviceSigningSecretKeyB64: String?,
|
|
221
222
|
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
222
223
|
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
223
224
|
) {
|
|
@@ -238,6 +239,24 @@ public final class PingNative: RCTEventEmitter {
|
|
|
238
239
|
}
|
|
239
240
|
sqliteKey = keyData
|
|
240
241
|
}
|
|
242
|
+
// Optional Ed25519 device signing secret. Same 32-byte
|
|
243
|
+
// shape as the SQLCipher key; loud-reject on mismatched
|
|
244
|
+
// length so callers find the bug at init time rather
|
|
245
|
+
// than via a server-side `sender_device_mismatch`
|
|
246
|
+
// hours later.
|
|
247
|
+
var deviceSigningSecret: Data? = nil
|
|
248
|
+
if let secretB64 = deviceSigningSecretKeyB64,
|
|
249
|
+
let secretData = Data(base64Encoded: secretB64) {
|
|
250
|
+
guard secretData.count == 32 else {
|
|
251
|
+
reject(
|
|
252
|
+
"InvalidDeviceSigningKey",
|
|
253
|
+
"deviceSigningSecretKey must be 32 bytes, got \(secretData.count)",
|
|
254
|
+
nil
|
|
255
|
+
)
|
|
256
|
+
return
|
|
257
|
+
}
|
|
258
|
+
deviceSigningSecret = secretData
|
|
259
|
+
}
|
|
241
260
|
// UniFFI's `[Name=init]` constructor generates a static factory named
|
|
242
261
|
// `init` (backquoted because Swift reserves the bare identifier for
|
|
243
262
|
// designated initializers).
|
|
@@ -248,7 +267,8 @@ public final class PingNative: RCTEventEmitter {
|
|
|
248
267
|
transport: self.transportBridge,
|
|
249
268
|
nowMs: UInt64(nowMs),
|
|
250
269
|
sqlitePath: sqlitePath,
|
|
251
|
-
sqliteEncryptionKey: sqliteKey
|
|
270
|
+
sqliteEncryptionKey: sqliteKey,
|
|
271
|
+
deviceSigningSecretKey: deviceSigningSecret
|
|
252
272
|
)
|
|
253
273
|
self.client = c
|
|
254
274
|
resolve(true)
|
package/ios/pingFFI.h
CHANGED
|
@@ -374,7 +374,7 @@ void uniffi_ping_ffi_fn_free_messagingclient(void*_Nonnull ptr, RustCallStatus *
|
|
|
374
374
|
#endif
|
|
375
375
|
#ifndef UNIFFI_FFIDEF_UNIFFI_PING_FFI_FN_CONSTRUCTOR_MESSAGINGCLIENT_INIT
|
|
376
376
|
#define UNIFFI_FFIDEF_UNIFFI_PING_FFI_FN_CONSTRUCTOR_MESSAGINGCLIENT_INIT
|
|
377
|
-
uint64_t uniffi_ping_ffi_fn_constructor_messagingclient_init(RustBuffer identity_export, RustBuffer device_label, void*_Nonnull storage, void*_Nonnull transport, uint64_t now_ms, RustBuffer sqlite_path, RustBuffer sqlite_encryption_key
|
|
377
|
+
uint64_t uniffi_ping_ffi_fn_constructor_messagingclient_init(RustBuffer identity_export, RustBuffer device_label, void*_Nonnull storage, void*_Nonnull transport, uint64_t now_ms, RustBuffer sqlite_path, RustBuffer sqlite_encryption_key, RustBuffer device_signing_secret_key
|
|
378
378
|
);
|
|
379
379
|
#endif
|
|
380
380
|
#ifndef UNIFFI_FFIDEF_UNIFFI_PING_FFI_FN_METHOD_MESSAGINGCLIENT_ADD_MEMBERS
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ping-openmls-sdk-react-native-macos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Real MLS for React Native macOS apps — wraps the ping-openmls-sdk Rust core via UniFFI.",
|
|
5
5
|
"homepage": "https://github.com/AMP-Media-Development/ping-openmls-sdk",
|
|
6
6
|
"license": "Apache-2.0",
|
package/src/MessagingClient.ts
CHANGED
|
@@ -37,6 +37,25 @@ export interface ClientConfig {
|
|
|
37
37
|
* from your OS keyring (Keychain on iOS, Keystore on Android, etc.).
|
|
38
38
|
*/
|
|
39
39
|
sqliteEncryptionKey?: Uint8Array;
|
|
40
|
+
/**
|
|
41
|
+
* Optional 32-byte Ed25519 secret key the SDK adopts as its device
|
|
42
|
+
* signing key on FIRST init. When supplied, `deviceId()` returns
|
|
43
|
+
* `SHA-256(public_key_of(secret))` — deterministic from what the
|
|
44
|
+
* caller passes.
|
|
45
|
+
*
|
|
46
|
+
* Use case: align the SDK's `device_id` (which the SDK stamps into
|
|
47
|
+
* every envelope's `sender_device` field) with an externally-
|
|
48
|
+
* computed device id — typically `SHA-256(device_signing_pubkey)`
|
|
49
|
+
* in the host's auth layer, where the JWT carries that same value
|
|
50
|
+
* as its `device_id` claim. Without this alignment, a server that
|
|
51
|
+
* validates `envelope.sender_device == jwt.device_id` rejects every
|
|
52
|
+
* send with `sender_device_mismatch`.
|
|
53
|
+
*
|
|
54
|
+
* Ignored on re-init when a `LocalDevice` is already persisted in
|
|
55
|
+
* storage — the on-disk identity is authoritative for stability
|
|
56
|
+
* across restarts.
|
|
57
|
+
*/
|
|
58
|
+
deviceSigningSecretKey?: Uint8Array;
|
|
40
59
|
}
|
|
41
60
|
|
|
42
61
|
/** [CR-2] One `(deviceId, keyPackage)` pair for `Conversation.addMembers`. */
|
|
@@ -85,12 +104,16 @@ export class MessagingClient {
|
|
|
85
104
|
const sqliteKeyB64 = cfg.sqliteEncryptionKey
|
|
86
105
|
? bytesToBase64(cfg.sqliteEncryptionKey)
|
|
87
106
|
: null;
|
|
107
|
+
const signingSecretB64 = cfg.deviceSigningSecretKey
|
|
108
|
+
? bytesToBase64(cfg.deviceSigningSecretKey)
|
|
109
|
+
: null;
|
|
88
110
|
await NativePing.initClient(
|
|
89
111
|
identityB64,
|
|
90
112
|
cfg.deviceLabel,
|
|
91
113
|
Date.now(),
|
|
92
114
|
cfg.sqlitePath ?? null,
|
|
93
115
|
sqliteKeyB64,
|
|
116
|
+
signingSecretB64,
|
|
94
117
|
);
|
|
95
118
|
} catch (e) {
|
|
96
119
|
// Init failed — disconnect the bridges so we don't leak event listeners.
|
package/src/NativePing.ts
CHANGED
|
@@ -59,6 +59,10 @@ export interface Spec extends TurboModule {
|
|
|
59
59
|
* (fine for tests / non-cold-start flows; **not** fine for NSE-style wake-ups).
|
|
60
60
|
* - [CR-4] `sqliteEncryptionKeyB64` — 32-byte SQLCipher key, base64-encoded. Ignored
|
|
61
61
|
* when `sqlitePath` is `null`. Pass `null` if you don't want at-rest encryption.
|
|
62
|
+
* - `deviceSigningSecretKeyB64` — optional 32-byte Ed25519 secret the SDK
|
|
63
|
+
* adopts as its device signing key on FIRST init. Pass `null` to keep
|
|
64
|
+
* the legacy random-key behaviour. See `ClientConfig.deviceSigningSecretKey`
|
|
65
|
+
* in MessagingClient.ts for the security rationale.
|
|
62
66
|
*
|
|
63
67
|
* Resolves to `true` on success, rejects with `InitFailed` (Rust error) or
|
|
64
68
|
* `InvalidIdentity` (base64 decode) on failure.
|
|
@@ -69,6 +73,7 @@ export interface Spec extends TurboModule {
|
|
|
69
73
|
nowMs: number,
|
|
70
74
|
sqlitePath: string | null,
|
|
71
75
|
sqliteEncryptionKeyB64: string | null,
|
|
76
|
+
deviceSigningSecretKeyB64: string | null,
|
|
72
77
|
): Promise<boolean>;
|
|
73
78
|
|
|
74
79
|
/** Returns the active client's user_id as a hex string. Rejects if not initialised. */
|