zapo-js 0.1.0 → 0.1.2
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/README.md +12 -7
- package/dist/appstate/WaAppStateCrypto.js +18 -25
- package/dist/appstate/WaAppStateSyncClient.js +181 -114
- package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
- package/dist/appstate/constants.js +4 -3
- package/dist/appstate/utils.js +10 -30
- package/dist/auth/WaAuthClient.js +48 -55
- package/dist/auth/flow/WaAuthCredentialsFlow.js +21 -14
- package/dist/auth/index.js +1 -3
- package/dist/auth/pairing/WaPairingFlow.js +21 -23
- package/dist/auth/pairing/WaQrFlow.js +37 -24
- package/dist/client/WaClient.js +103 -276
- package/dist/client/WaClientFactory.js +227 -110
- package/dist/client/connection/WaConnectionManager.js +292 -0
- package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
- package/dist/client/connection/WaReceiptQueue.js +51 -0
- package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
- package/dist/client/coordinators/WaGroupCoordinator.js +27 -17
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +231 -686
- package/dist/client/coordinators/WaRetryCoordinator.js +70 -37
- package/dist/client/dirty.js +35 -29
- package/dist/client/events/chat.js +4 -3
- package/dist/client/events/group.js +59 -36
- package/dist/client/history-sync.js +53 -63
- package/dist/client/incoming.js +23 -20
- package/dist/client/mailbox.js +8 -8
- package/dist/client/messages.js +4 -4
- package/dist/client/messaging/fanout.js +189 -0
- package/dist/client/messaging/key-protocol.js +130 -0
- package/dist/client/messaging/participants.js +191 -0
- package/dist/crypto/core/hkdf.js +3 -8
- package/dist/crypto/core/index.js +1 -4
- package/dist/crypto/core/keys.js +2 -3
- package/dist/crypto/core/primitives.js +12 -15
- package/dist/crypto/core/random.js +7 -26
- package/dist/crypto/curves/Ed25519.js +7 -8
- package/dist/crypto/curves/X25519.js +13 -16
- package/dist/crypto/index.js +0 -5
- package/dist/esm/appstate/WaAppStateCrypto.js +6 -13
- package/dist/esm/appstate/WaAppStateSyncClient.js +174 -107
- package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
- package/dist/esm/appstate/constants.js +3 -2
- package/dist/esm/appstate/utils.js +8 -27
- package/dist/esm/auth/WaAuthClient.js +48 -55
- package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +21 -14
- package/dist/esm/auth/index.js +0 -1
- package/dist/esm/auth/pairing/WaPairingFlow.js +14 -16
- package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
- package/dist/esm/client/WaClient.js +103 -276
- package/dist/esm/client/WaClientFactory.js +227 -110
- package/dist/esm/client/connection/WaConnectionManager.js +288 -0
- package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
- package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
- package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
- package/dist/esm/client/coordinators/WaGroupCoordinator.js +20 -10
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +232 -687
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +71 -38
- package/dist/esm/client/dirty.js +30 -24
- package/dist/esm/client/events/chat.js +4 -3
- package/dist/esm/client/events/group.js +50 -28
- package/dist/esm/client/history-sync.js +50 -60
- package/dist/esm/client/incoming.js +23 -20
- package/dist/esm/client/mailbox.js +8 -8
- package/dist/esm/client/messages.js +1 -1
- package/dist/esm/client/messaging/fanout.js +186 -0
- package/dist/esm/client/messaging/key-protocol.js +127 -0
- package/dist/esm/client/messaging/participants.js +188 -0
- package/dist/esm/crypto/core/hkdf.js +3 -8
- package/dist/esm/crypto/core/index.js +0 -1
- package/dist/esm/crypto/core/keys.js +2 -3
- package/dist/esm/crypto/core/primitives.js +12 -15
- package/dist/esm/crypto/core/random.js +6 -25
- package/dist/esm/crypto/curves/Ed25519.js +4 -5
- package/dist/esm/crypto/curves/X25519.js +10 -13
- package/dist/esm/crypto/index.js +0 -2
- package/dist/esm/infra/log/ConsoleLogger.js +18 -17
- package/dist/esm/infra/log/PinoLogger.js +15 -9
- package/dist/esm/infra/log/types.js +11 -1
- package/dist/esm/infra/perf/BoundedTaskQueue.js +13 -17
- package/dist/esm/media/WaMediaCrypto.js +2 -4
- package/dist/esm/media/WaMediaTransferClient.js +226 -58
- package/dist/esm/media/conn.js +10 -6
- package/dist/esm/media/constants.js +4 -1
- package/dist/esm/message/WaMessageClient.js +4 -13
- package/dist/esm/message/ack.js +6 -6
- package/dist/esm/message/addon-crypto.js +59 -0
- package/dist/esm/message/incoming.js +106 -111
- package/dist/esm/message/index.js +2 -0
- package/dist/esm/message/reporting-token.js +438 -0
- package/dist/esm/message/use-case-secret.js +49 -0
- package/dist/esm/protocol/appstate.js +58 -0
- package/dist/esm/protocol/constants.js +2 -1
- package/dist/esm/protocol/index.js +2 -10
- package/dist/esm/protocol/jid.js +63 -51
- package/dist/esm/protocol/media.js +3 -3
- package/dist/esm/protocol/nodes.js +2 -0
- package/dist/esm/protocol/usync.js +11 -0
- package/dist/esm/retry/index.js +1 -0
- package/dist/esm/retry/outbound.js +4 -5
- package/dist/esm/retry/parse.js +58 -76
- package/dist/esm/retry/replay.js +48 -49
- package/dist/esm/retry/tracker.js +56 -0
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +249 -82
- package/dist/esm/signal/api/SignalDigestSyncApi.js +6 -1
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +49 -34
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +70 -62
- package/dist/esm/signal/api/SignalSessionSyncApi.js +23 -30
- package/dist/esm/signal/crypto/WaAdvSignature.js +3 -5
- package/dist/esm/signal/group/SenderKeyChain.js +28 -23
- package/dist/esm/signal/group/SenderKeyCodec.js +2 -4
- package/dist/esm/signal/group/SenderKeyManager.js +26 -16
- package/dist/esm/signal/index.js +1 -0
- package/dist/esm/signal/session/SignalProtocol.js +49 -14
- package/dist/esm/signal/session/SignalRatchet.js +24 -15
- package/dist/esm/signal/session/SignalSession.js +14 -9
- package/dist/esm/signal/session/resolver.js +186 -0
- package/dist/esm/signal/store/sqlite.js +16 -37
- package/dist/esm/store/createStore.js +16 -18
- package/dist/esm/store/noop.store.js +3 -6
- package/dist/esm/store/providers/memory/appstate.store.js +30 -6
- package/dist/esm/store/providers/memory/contact.store.js +5 -0
- package/dist/esm/store/providers/memory/device-list.store.js +3 -30
- package/dist/esm/store/providers/memory/message.store.js +11 -5
- package/dist/esm/store/providers/memory/participants.store.js +1 -8
- package/dist/esm/store/providers/memory/sender-key.store.js +5 -7
- package/dist/esm/store/providers/memory/signal.store.js +13 -1
- package/dist/esm/store/providers/memory/thread.store.js +5 -0
- package/dist/esm/store/providers/sqlite/appstate.store.js +82 -1
- package/dist/esm/store/providers/sqlite/connection.js +18 -13
- package/dist/esm/store/providers/sqlite/contact.store.js +31 -18
- package/dist/esm/store/providers/sqlite/device-list.store.js +7 -35
- package/dist/esm/store/providers/sqlite/message.store.js +45 -32
- package/dist/esm/store/providers/sqlite/migrations.js +1 -1
- package/dist/esm/store/providers/sqlite/participants.store.js +1 -9
- package/dist/esm/store/providers/sqlite/retry.store.js +8 -11
- package/dist/esm/store/providers/sqlite/sender-key.store.js +25 -30
- package/dist/esm/store/providers/sqlite/signal.store.js +104 -22
- package/dist/esm/store/providers/sqlite/table-names.js +107 -0
- package/dist/esm/store/providers/sqlite/thread.store.js +35 -22
- package/dist/esm/transport/WaComms.js +25 -23
- package/dist/esm/transport/WaWebSocket.js +115 -12
- package/dist/esm/transport/binary/decoder.js +4 -4
- package/dist/esm/transport/binary/encoder.js +12 -4
- package/dist/esm/transport/index.js +1 -0
- package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
- package/dist/esm/transport/node/WaNodeOrchestrator.js +2 -4
- package/dist/esm/transport/node/WaNodeTransport.js +0 -3
- package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
- package/dist/esm/transport/node/builders/index.js +2 -1
- package/dist/esm/transport/node/builders/message.js +9 -0
- package/dist/esm/transport/node/builders/pairing.js +4 -5
- package/dist/esm/transport/node/builders/usync.js +41 -0
- package/dist/esm/transport/node/helpers.js +107 -5
- package/dist/esm/transport/node/usync.js +35 -0
- package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
- package/dist/esm/transport/noise/WaNoiseCert.js +3 -6
- package/dist/esm/transport/noise/WaNoiseSession.js +17 -10
- package/dist/esm/transport/proxy.js +27 -0
- package/dist/esm/transport/stream/parse.js +13 -48
- package/dist/esm/util/bytes.js +50 -32
- package/dist/esm/util/coercion.js +6 -14
- package/dist/esm/util/primitives.js +39 -14
- package/dist/infra/log/ConsoleLogger.js +18 -17
- package/dist/infra/log/PinoLogger.js +15 -9
- package/dist/infra/log/types.js +12 -0
- package/dist/infra/perf/BoundedTaskQueue.js +13 -17
- package/dist/media/WaMediaCrypto.js +1 -3
- package/dist/media/WaMediaTransferClient.js +259 -58
- package/dist/media/conn.js +10 -6
- package/dist/media/constants.js +4 -1
- package/dist/message/WaMessageClient.js +5 -14
- package/dist/message/ack.js +6 -6
- package/dist/message/addon-crypto.js +65 -0
- package/dist/message/incoming.js +104 -109
- package/dist/message/index.js +2 -0
- package/dist/message/reporting-token.js +443 -0
- package/dist/message/use-case-secret.js +55 -0
- package/dist/protocol/appstate.js +59 -1
- package/dist/protocol/constants.js +7 -1
- package/dist/protocol/index.js +20 -42
- package/dist/protocol/jid.js +64 -51
- package/dist/protocol/media.js +3 -3
- package/dist/protocol/nodes.js +2 -0
- package/dist/protocol/usync.js +14 -0
- package/dist/retry/index.js +3 -1
- package/dist/retry/outbound.js +6 -7
- package/dist/retry/parse.js +57 -75
- package/dist/retry/replay.js +46 -47
- package/dist/retry/tracker.js +59 -0
- package/dist/signal/api/SignalDeviceSyncApi.js +247 -80
- package/dist/signal/api/SignalDigestSyncApi.js +6 -1
- package/dist/signal/api/SignalIdentitySyncApi.js +49 -34
- package/dist/signal/api/SignalMissingPreKeysSyncApi.js +67 -59
- package/dist/signal/api/SignalSessionSyncApi.js +23 -30
- package/dist/signal/crypto/WaAdvSignature.js +2 -4
- package/dist/signal/group/SenderKeyChain.js +27 -22
- package/dist/signal/group/SenderKeyCodec.js +1 -3
- package/dist/signal/group/SenderKeyManager.js +26 -16
- package/dist/signal/index.js +3 -1
- package/dist/signal/session/SignalProtocol.js +49 -14
- package/dist/signal/session/SignalRatchet.js +24 -15
- package/dist/signal/session/SignalSession.js +14 -9
- package/dist/signal/session/resolver.js +189 -0
- package/dist/signal/store/sqlite.js +16 -37
- package/dist/store/createStore.js +16 -18
- package/dist/store/noop.store.js +3 -6
- package/dist/store/providers/memory/appstate.store.js +28 -4
- package/dist/store/providers/memory/contact.store.js +5 -0
- package/dist/store/providers/memory/device-list.store.js +3 -30
- package/dist/store/providers/memory/message.store.js +11 -5
- package/dist/store/providers/memory/participants.store.js +1 -8
- package/dist/store/providers/memory/sender-key.store.js +8 -10
- package/dist/store/providers/memory/signal.store.js +21 -9
- package/dist/store/providers/memory/thread.store.js +5 -0
- package/dist/store/providers/sqlite/appstate.store.js +81 -0
- package/dist/store/providers/sqlite/connection.js +18 -13
- package/dist/store/providers/sqlite/contact.store.js +31 -18
- package/dist/store/providers/sqlite/device-list.store.js +7 -35
- package/dist/store/providers/sqlite/message.store.js +45 -32
- package/dist/store/providers/sqlite/migrations.js +1 -1
- package/dist/store/providers/sqlite/participants.store.js +1 -9
- package/dist/store/providers/sqlite/retry.store.js +8 -11
- package/dist/store/providers/sqlite/sender-key.store.js +24 -29
- package/dist/store/providers/sqlite/signal.store.js +105 -23
- package/dist/store/providers/sqlite/table-names.js +113 -0
- package/dist/store/providers/sqlite/thread.store.js +35 -22
- package/dist/transport/WaComms.js +27 -25
- package/dist/transport/WaWebSocket.js +148 -12
- package/dist/transport/binary/decoder.js +4 -4
- package/dist/transport/binary/encoder.js +12 -4
- package/dist/transport/index.js +7 -1
- package/dist/transport/keepalive/WaKeepAlive.js +1 -7
- package/dist/transport/node/WaNodeOrchestrator.js +2 -4
- package/dist/transport/node/WaNodeTransport.js +0 -3
- package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
- package/dist/transport/node/builders/index.js +12 -9
- package/dist/transport/node/builders/message.js +9 -0
- package/dist/transport/node/builders/pairing.js +4 -5
- package/dist/transport/node/builders/usync.js +45 -0
- package/dist/transport/node/helpers.js +112 -4
- package/dist/transport/node/usync.js +38 -0
- package/dist/transport/noise/WaFrameCodec.js +47 -32
- package/dist/transport/noise/WaNoiseCert.js +5 -8
- package/dist/transport/noise/WaNoiseSession.js +17 -10
- package/dist/transport/proxy.js +34 -0
- package/dist/transport/stream/parse.js +17 -53
- package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
- package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
- package/dist/types/appstate/constants.d.ts +1 -0
- package/dist/types/appstate/store/sqlite.d.ts +4 -18
- package/dist/types/appstate/utils.d.ts +0 -1
- package/dist/types/auth/WaAuthClient.d.ts +10 -12
- package/dist/types/auth/index.d.ts +0 -2
- package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
- package/dist/types/auth/types.d.ts +6 -9
- package/dist/types/client/WaClient.d.ts +27 -25
- package/dist/types/client/WaClientFactory.d.ts +22 -23
- package/dist/types/client/connection/WaConnectionManager.d.ts +64 -0
- package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
- package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
- package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +0 -1
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +18 -41
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +2 -0
- package/dist/types/client/dirty.d.ts +1 -0
- package/dist/types/client/events/group.d.ts +2 -1
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/messaging/fanout.d.ts +14 -0
- package/dist/types/client/messaging/key-protocol.d.ts +18 -0
- package/dist/types/client/messaging/participants.d.ts +13 -0
- package/dist/types/client/types.d.ts +24 -1
- package/dist/types/crypto/core/hkdf.d.ts +0 -6
- package/dist/types/crypto/core/index.d.ts +0 -1
- package/dist/types/crypto/core/random.d.ts +1 -7
- package/dist/types/crypto/index.d.ts +0 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
- package/dist/types/infra/log/PinoLogger.d.ts +1 -1
- package/dist/types/infra/log/types.d.ts +1 -0
- package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
- package/dist/types/media/WaMediaTransferClient.d.ts +13 -3
- package/dist/types/media/types.d.ts +5 -0
- package/dist/types/message/addon-crypto.d.ts +25 -0
- package/dist/types/message/index.d.ts +2 -0
- package/dist/types/message/reporting-token.d.ts +19 -0
- package/dist/types/message/use-case-secret.d.ts +20 -0
- package/dist/types/protocol/appstate.d.ts +58 -0
- package/dist/types/protocol/constants.d.ts +2 -1
- package/dist/types/protocol/index.d.ts +2 -10
- package/dist/types/protocol/jid.d.ts +3 -3
- package/dist/types/protocol/nodes.d.ts +2 -0
- package/dist/types/protocol/usync.d.ts +11 -0
- package/dist/types/retry/index.d.ts +1 -0
- package/dist/types/retry/replay.d.ts +0 -4
- package/dist/types/retry/tracker.d.ts +19 -0
- package/dist/types/retry/types.d.ts +4 -3
- package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +13 -1
- package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
- package/dist/types/signal/index.d.ts +1 -0
- package/dist/types/signal/session/SignalProtocol.d.ts +9 -0
- package/dist/types/signal/session/resolver.d.ts +17 -0
- package/dist/types/store/contracts/appstate.store.d.ts +3 -0
- package/dist/types/store/contracts/contact.store.d.ts +1 -0
- package/dist/types/store/contracts/device-list.store.d.ts +0 -3
- package/dist/types/store/contracts/message.store.d.ts +1 -0
- package/dist/types/store/contracts/participants.store.d.ts +0 -1
- package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
- package/dist/types/store/contracts/signal.store.d.ts +6 -0
- package/dist/types/store/contracts/thread.store.d.ts +1 -0
- package/dist/types/store/index.d.ts +1 -1
- package/dist/types/store/providers/memory/appstate.store.d.ts +2 -0
- package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
- package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
- package/dist/types/store/providers/memory/message.store.d.ts +1 -0
- package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
- package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
- package/dist/types/store/providers/memory/signal.store.d.ts +6 -0
- package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
- package/dist/types/store/providers/sqlite/appstate.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/contact.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -3
- package/dist/types/store/providers/sqlite/message.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/signal.store.d.ts +7 -0
- package/dist/types/store/providers/sqlite/table-names.d.ts +5 -0
- package/dist/types/store/providers/sqlite/thread.store.d.ts +2 -0
- package/dist/types/store/types.d.ts +3 -0
- package/dist/types/transport/WaWebSocket.d.ts +3 -0
- package/dist/types/transport/index.d.ts +2 -1
- package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
- package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
- package/dist/types/transport/node/builders/group.d.ts +4 -6
- package/dist/types/transport/node/builders/index.d.ts +2 -1
- package/dist/types/transport/node/builders/message.d.ts +14 -25
- package/dist/types/transport/node/builders/retry.d.ts +2 -4
- package/dist/types/transport/node/builders/usync.d.ts +21 -0
- package/dist/types/transport/node/helpers.d.ts +8 -0
- package/dist/types/transport/node/usync.d.ts +2 -0
- package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
- package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -0
- package/dist/types/transport/proxy.d.ts +6 -0
- package/dist/types/transport/stream/parse.d.ts +0 -1
- package/dist/types/transport/types.d.ts +18 -1
- package/dist/types/util/bytes.d.ts +5 -0
- package/dist/types/util/primitives.d.ts +3 -0
- package/dist/util/bytes.js +55 -33
- package/dist/util/coercion.js +6 -14
- package/dist/util/primitives.js +42 -14
- package/package.json +27 -9
- package/proto/index.d.ts +1090 -1048
- package/proto/index.js +1 -1
- package/scripts/check-node-version.cjs +0 -1
- package/dist/crypto/core/encoding.js +0 -29
- package/dist/esm/crypto/core/encoding.js +0 -25
- package/dist/esm/util/base64.js +0 -18
- package/dist/esm/util/signal-address.js +0 -5
- package/dist/types/crypto/core/encoding.d.ts +0 -11
- package/dist/types/util/base64.d.ts +0 -4
- package/dist/types/util/signal-address.d.ts +0 -2
- package/dist/util/base64.js +0 -24
- package/dist/util/signal-address.js +0 -8
- /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
|
@@ -8,16 +8,6 @@ const constants_2 = require("../api/constants");
|
|
|
8
8
|
const prekeys_1 = require("../api/prekeys");
|
|
9
9
|
const helpers_1 = require("../../transport/node/helpers");
|
|
10
10
|
const query_1 = require("../../transport/node/query");
|
|
11
|
-
function parseDeviceId(value, field) {
|
|
12
|
-
if (!value) {
|
|
13
|
-
throw new Error(`${field} is missing`);
|
|
14
|
-
}
|
|
15
|
-
const parsed = Number.parseInt(value, 10);
|
|
16
|
-
if (!Number.isSafeInteger(parsed) || parsed < 0) {
|
|
17
|
-
throw new Error(`${field} is invalid`);
|
|
18
|
-
}
|
|
19
|
-
return parsed;
|
|
20
|
-
}
|
|
21
11
|
class SignalMissingPreKeysSyncApi {
|
|
22
12
|
constructor(options) {
|
|
23
13
|
this.logger = options.logger;
|
|
@@ -41,16 +31,7 @@ class SignalMissingPreKeysSyncApi {
|
|
|
41
31
|
return parsed;
|
|
42
32
|
}
|
|
43
33
|
parseFetchMissingPreKeysResponse(node, requestedTargets) {
|
|
44
|
-
|
|
45
|
-
throw new Error(`invalid missing prekeys response tag: ${node.tag}`);
|
|
46
|
-
}
|
|
47
|
-
if (node.attrs.type === constants_1.WA_IQ_TYPES.ERROR) {
|
|
48
|
-
const error = (0, query_1.parseIqError)(node);
|
|
49
|
-
throw new Error(`missing prekeys iq failed (${error.code}: ${error.text})`);
|
|
50
|
-
}
|
|
51
|
-
if (node.attrs.type !== constants_1.WA_IQ_TYPES.RESULT) {
|
|
52
|
-
throw new Error(`invalid missing prekeys response type: ${node.attrs.type ?? 'unknown'}`);
|
|
53
|
-
}
|
|
34
|
+
(0, query_1.assertIqResult)(node, 'missing prekeys');
|
|
54
35
|
const listNode = (0, helpers_1.findNodeChild)(node, constants_1.WA_NODE_TAGS.LIST);
|
|
55
36
|
if (!listNode) {
|
|
56
37
|
throw new Error('missing prekeys response missing list node');
|
|
@@ -78,68 +59,95 @@ class SignalMissingPreKeysSyncApi {
|
|
|
78
59
|
devices: this.parseUserDevices(userNode, userJid)
|
|
79
60
|
});
|
|
80
61
|
}
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
const results = new Array(requestedTargets.length);
|
|
63
|
+
for (let index = 0; index < requestedTargets.length; index += 1) {
|
|
64
|
+
const target = requestedTargets[index];
|
|
65
|
+
results[index] = parsedByJid.get(target.userJid) ?? {
|
|
83
66
|
userJid: target.userJid,
|
|
84
67
|
errorText: 'missing user in key_fetch response'
|
|
85
|
-
}
|
|
86
|
-
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return results;
|
|
87
71
|
}
|
|
88
72
|
parseUserDevices(node, userJid) {
|
|
89
73
|
const { user, server } = (0, jid_1.splitJid)(userJid);
|
|
90
74
|
const devices = (0, helpers_1.getNodeChildrenByTag)(node, constants_1.WA_NODE_TAGS.DEVICE);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
|
|
75
|
+
const bundles = new Array(devices.length);
|
|
76
|
+
for (let index = 0; index < devices.length; index += 1) {
|
|
77
|
+
const deviceNode = devices[index];
|
|
78
|
+
const deviceIdValue = deviceNode.attrs.id;
|
|
79
|
+
if (!deviceIdValue) {
|
|
80
|
+
throw new Error(`missing prekeys device[${index}].id is missing`);
|
|
81
|
+
}
|
|
82
|
+
const deviceId = Number.parseInt(deviceIdValue, 10);
|
|
83
|
+
if (!Number.isSafeInteger(deviceId) || deviceId < 0) {
|
|
84
|
+
throw new Error(`missing prekeys device[${index}].id is invalid`);
|
|
85
|
+
}
|
|
86
|
+
const [registrationNode, identityNode, signedKeyNode, oneTimeNode, deviceIdentityNode] = (0, helpers_1.findNodeChildrenByTags)(deviceNode, [
|
|
87
|
+
constants_1.WA_NODE_TAGS.REGISTRATION,
|
|
88
|
+
constants_1.WA_NODE_TAGS.IDENTITY,
|
|
89
|
+
constants_1.WA_NODE_TAGS.SKEY,
|
|
90
|
+
constants_1.WA_NODE_TAGS.KEY,
|
|
91
|
+
constants_1.WA_NODE_TAGS.DEVICE_IDENTITY
|
|
92
|
+
]);
|
|
96
93
|
if (!registrationNode || !identityNode || !signedKeyNode) {
|
|
97
94
|
throw new Error(`missing prekeys device payload is incomplete for ${userJid}`);
|
|
98
95
|
}
|
|
99
|
-
const signedKeyIdNode = (0, helpers_1.
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
const [signedKeyIdNode, signedKeyValueNode, signedKeySignatureNode] = (0, helpers_1.findNodeChildrenByTags)(signedKeyNode, [
|
|
97
|
+
constants_1.WA_NODE_TAGS.ID,
|
|
98
|
+
constants_1.WA_NODE_TAGS.VALUE,
|
|
99
|
+
constants_1.WA_NODE_TAGS.SIGNATURE
|
|
100
|
+
]);
|
|
102
101
|
if (!signedKeyIdNode || !signedKeyValueNode || !signedKeySignatureNode) {
|
|
103
102
|
throw new Error(`missing prekeys signed pre-key is incomplete for ${userJid}`);
|
|
104
103
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
let oneTimeIdNode;
|
|
105
|
+
let oneTimeValueNode;
|
|
106
|
+
if (oneTimeNode) {
|
|
107
|
+
const oneTimeNodes = (0, helpers_1.findNodeChildrenByTags)(oneTimeNode, [
|
|
108
|
+
constants_1.WA_NODE_TAGS.ID,
|
|
109
|
+
constants_1.WA_NODE_TAGS.VALUE
|
|
110
|
+
]);
|
|
111
|
+
oneTimeIdNode = oneTimeNodes[0];
|
|
112
|
+
oneTimeValueNode = oneTimeNodes[1];
|
|
113
|
+
}
|
|
112
114
|
if (oneTimeNode && (!oneTimeIdNode || !oneTimeValueNode)) {
|
|
113
115
|
throw new Error(`missing prekeys one-time key is incomplete for ${userJid}`);
|
|
114
116
|
}
|
|
115
|
-
const
|
|
116
|
-
const bundle = {
|
|
117
|
+
const baseBundle = {
|
|
117
118
|
regId: (0, codec_1.parseUint)((0, codec_1.decodeExactLength)(registrationNode.content, 'missing prekeys device registration', constants_2.SIGNAL_REGISTRATION_ID_LENGTH), 'missing prekeys device registration'),
|
|
118
119
|
identity: (0, codec_1.decodeExactLength)(identityNode.content, 'missing prekeys device identity', constants_2.SIGNAL_KEY_DATA_LENGTH),
|
|
119
120
|
signedKey: {
|
|
120
121
|
id: (0, codec_1.parseUint)((0, codec_1.decodeExactLength)(signedKeyIdNode.content, 'missing prekeys device skey.id', constants_2.SIGNAL_KEY_ID_LENGTH), 'missing prekeys device skey.id'),
|
|
121
122
|
publicKey: (0, codec_1.decodeExactLength)(signedKeyValueNode.content, 'missing prekeys device skey.value', constants_2.SIGNAL_KEY_DATA_LENGTH),
|
|
122
123
|
signature: (0, codec_1.decodeExactLength)(signedKeySignatureNode.content, 'missing prekeys device skey.signature', constants_2.SIGNAL_SIGNATURE_LENGTH)
|
|
123
|
-
}
|
|
124
|
-
...(oneTimeIdNode && oneTimeValueNode
|
|
125
|
-
? {
|
|
126
|
-
oneTimeKey: {
|
|
127
|
-
id: (0, codec_1.parseUint)((0, codec_1.decodeExactLength)(oneTimeIdNode.content, 'missing prekeys device key.id', constants_2.SIGNAL_KEY_ID_LENGTH), 'missing prekeys device key.id'),
|
|
128
|
-
publicKey: (0, codec_1.decodeExactLength)(oneTimeValueNode.content, 'missing prekeys device key.value', constants_2.SIGNAL_KEY_DATA_LENGTH)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
: {})
|
|
124
|
+
}
|
|
132
125
|
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
126
|
+
const bundle = oneTimeIdNode && oneTimeValueNode
|
|
127
|
+
? {
|
|
128
|
+
...baseBundle,
|
|
129
|
+
oneTimeKey: {
|
|
130
|
+
id: (0, codec_1.parseUint)((0, codec_1.decodeExactLength)(oneTimeIdNode.content, 'missing prekeys device key.id', constants_2.SIGNAL_KEY_ID_LENGTH), 'missing prekeys device key.id'),
|
|
131
|
+
publicKey: (0, codec_1.decodeExactLength)(oneTimeValueNode.content, 'missing prekeys device key.value', constants_2.SIGNAL_KEY_DATA_LENGTH)
|
|
139
132
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
133
|
+
}
|
|
134
|
+
: baseBundle;
|
|
135
|
+
let deviceIdentity;
|
|
136
|
+
if (deviceIdentityNode) {
|
|
137
|
+
deviceIdentity = (0, helpers_1.decodeNodeContentBase64OrBytes)(deviceIdentityNode.content, 'missing prekeys device device-identity');
|
|
138
|
+
}
|
|
139
|
+
bundles[index] = deviceIdentity
|
|
140
|
+
? {
|
|
141
|
+
deviceJid: deviceId === 0 ? userJid : `${user}:${deviceId}@${server}`,
|
|
142
|
+
bundle,
|
|
143
|
+
deviceIdentity
|
|
144
|
+
}
|
|
145
|
+
: {
|
|
146
|
+
deviceJid: deviceId === 0 ? userJid : `${user}:${deviceId}@${server}`,
|
|
147
|
+
bundle
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return bundles;
|
|
143
151
|
}
|
|
144
152
|
}
|
|
145
153
|
exports.SignalMissingPreKeysSyncApi = SignalMissingPreKeysSyncApi;
|
|
@@ -5,6 +5,7 @@ const constants_1 = require("../../protocol/constants");
|
|
|
5
5
|
const codec_1 = require("../api/codec");
|
|
6
6
|
const constants_2 = require("../api/constants");
|
|
7
7
|
const helpers_1 = require("../../transport/node/helpers");
|
|
8
|
+
const query_1 = require("../../transport/node/query");
|
|
8
9
|
class SignalSessionSyncApi {
|
|
9
10
|
constructor(options) {
|
|
10
11
|
this.logger = options.logger;
|
|
@@ -43,7 +44,20 @@ class SignalSessionSyncApi {
|
|
|
43
44
|
reasonIdentity: (previous?.reasonIdentity ?? false) || target.reasonIdentity === true
|
|
44
45
|
});
|
|
45
46
|
}
|
|
46
|
-
const mergedTargets = [
|
|
47
|
+
const mergedTargets = [];
|
|
48
|
+
for (const target of targetByJid.values()) {
|
|
49
|
+
mergedTargets.push(target);
|
|
50
|
+
}
|
|
51
|
+
const userNodes = new Array(mergedTargets.length);
|
|
52
|
+
for (let index = 0; index < mergedTargets.length; index += 1) {
|
|
53
|
+
const target = mergedTargets[index];
|
|
54
|
+
userNodes[index] = {
|
|
55
|
+
tag: constants_1.WA_NODE_TAGS.USER,
|
|
56
|
+
attrs: target.reasonIdentity === true
|
|
57
|
+
? { jid: target.jid, reason: 'identity' }
|
|
58
|
+
: { jid: target.jid }
|
|
59
|
+
};
|
|
60
|
+
}
|
|
47
61
|
this.logger.debug('signal fetch key bundles request', {
|
|
48
62
|
targets: mergedTargets.length,
|
|
49
63
|
timeoutMs
|
|
@@ -59,34 +73,14 @@ class SignalSessionSyncApi {
|
|
|
59
73
|
{
|
|
60
74
|
tag: constants_1.WA_NODE_TAGS.KEY,
|
|
61
75
|
attrs: {},
|
|
62
|
-
content:
|
|
63
|
-
tag: constants_1.WA_NODE_TAGS.USER,
|
|
64
|
-
attrs: {
|
|
65
|
-
jid: target.jid,
|
|
66
|
-
...(target.reasonIdentity === true ? { reason: 'identity' } : {})
|
|
67
|
-
}
|
|
68
|
-
}))
|
|
76
|
+
content: userNodes
|
|
69
77
|
}
|
|
70
78
|
]
|
|
71
79
|
}, timeoutMs);
|
|
72
80
|
return this.parseFetchKeyBundleResponse(responseNode, mergedTargets);
|
|
73
81
|
}
|
|
74
82
|
parseFetchKeyBundleResponse(node, requestedTargets) {
|
|
75
|
-
|
|
76
|
-
throw new Error(`invalid key bundle response tag: ${node.tag}`);
|
|
77
|
-
}
|
|
78
|
-
if (node.attrs.type === constants_1.WA_IQ_TYPES.ERROR) {
|
|
79
|
-
const errorNode = (0, helpers_1.findNodeChild)(node, constants_1.WA_NODE_TAGS.ERROR);
|
|
80
|
-
if (!errorNode) {
|
|
81
|
-
throw new Error(`key bundle iq error for ${node.attrs.id ?? 'unknown id'}`);
|
|
82
|
-
}
|
|
83
|
-
const code = errorNode.attrs.code ?? 'unknown';
|
|
84
|
-
const text = errorNode.attrs.text ?? errorNode.attrs.type ?? 'unknown';
|
|
85
|
-
throw new Error(`key bundle iq error (${code} ${text})`);
|
|
86
|
-
}
|
|
87
|
-
if (node.attrs.type !== constants_1.WA_IQ_TYPES.RESULT) {
|
|
88
|
-
throw new Error(`invalid key bundle response type: ${node.attrs.type ?? 'unknown'}`);
|
|
89
|
-
}
|
|
83
|
+
(0, query_1.assertIqResult)(node, 'key bundle');
|
|
90
84
|
const listNode = (0, helpers_1.findNodeChild)(node, constants_1.WA_NODE_TAGS.LIST);
|
|
91
85
|
if (!listNode) {
|
|
92
86
|
throw new Error('key bundle response missing list node');
|
|
@@ -118,16 +112,15 @@ class SignalSessionSyncApi {
|
|
|
118
112
|
...(parsed.deviceIdentity ? { deviceIdentity: parsed.deviceIdentity } : {})
|
|
119
113
|
});
|
|
120
114
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
return {
|
|
115
|
+
const output = new Array(requestedTargets.length);
|
|
116
|
+
for (let index = 0; index < requestedTargets.length; index += 1) {
|
|
117
|
+
const target = requestedTargets[index];
|
|
118
|
+
output[index] = parsedByJid.get(target.jid) ?? {
|
|
127
119
|
jid: target.jid,
|
|
128
120
|
errorText: 'missing key bundle user in response'
|
|
129
121
|
};
|
|
130
|
-
}
|
|
122
|
+
}
|
|
123
|
+
return output;
|
|
131
124
|
}
|
|
132
125
|
parseUserKeyBundle(node) {
|
|
133
126
|
const registrationNode = (0, helpers_1.findNodeChild)(node, constants_1.WA_NODE_TAGS.REGISTRATION);
|
|
@@ -19,7 +19,7 @@ Object.defineProperty(exports, "ADV_PREFIX_DEVICE_SIGNATURE", { enumerable: true
|
|
|
19
19
|
Object.defineProperty(exports, "ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE", { enumerable: true, get: function () { return constants_2.ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE; } });
|
|
20
20
|
Object.defineProperty(exports, "ADV_PREFIX_HOSTED_DEVICE_SIGNATURE", { enumerable: true, get: function () { return constants_2.ADV_PREFIX_HOSTED_DEVICE_SIGNATURE; } });
|
|
21
21
|
async function verifySignalSignature(publicKey, message, signature) {
|
|
22
|
-
if (signature
|
|
22
|
+
if (!(0, bytes_1.assertByteLength)(signature, 64, 'invalid signal signature length', false)) {
|
|
23
23
|
return false;
|
|
24
24
|
}
|
|
25
25
|
if ((signature[63] & 0x60) !== 0) {
|
|
@@ -33,9 +33,7 @@ async function verifySignalSignature(publicKey, message, signature) {
|
|
|
33
33
|
return (0, _crypto_1.ed25519VerifyRaw)(edPublic, signalSignature, message);
|
|
34
34
|
}
|
|
35
35
|
async function signSignalMessage(privateKey, message) {
|
|
36
|
-
|
|
37
|
-
throw new Error(`invalid curve25519 private key length ${privateKey.length}`);
|
|
38
|
-
}
|
|
36
|
+
(0, bytes_1.assertByteLength)(privateKey, 32, `invalid curve25519 private key length ${privateKey.length}`);
|
|
39
37
|
const clampedPrivateKey = (0, X25519_1.clampCurvePrivateKeyInPlace)(privateKey);
|
|
40
38
|
const privateScalar = (0, le_1.bytesToBigIntLE)(clampedPrivateKey);
|
|
41
39
|
const encodedPublic = (0, edwards_1.encodeExtendedPoint)((0, edwards_1.scalarMultBase)(privateScalar));
|
|
@@ -30,24 +30,33 @@ async function selectMessageKey(senderKey, targetIteration) {
|
|
|
30
30
|
const firstDerived = await deriveSenderKeyMsgKeyFromState(senderKey.iteration, chainState);
|
|
31
31
|
chainState = firstDerived.nextState;
|
|
32
32
|
let messageKey = firstDerived.messageKey;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
if (delta === 0) {
|
|
34
|
+
return {
|
|
35
|
+
messageKey,
|
|
36
|
+
updatedRecord: {
|
|
37
|
+
...senderKey,
|
|
38
|
+
iteration: targetIteration + 1,
|
|
39
|
+
chainKey: chainState.chainKey,
|
|
40
|
+
unusedMessageKeys: currentUnused
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const nextUnused = currentUnused.slice();
|
|
45
|
+
let overflow = delta + currentUnused.length - constants_1.MAX_UNUSED_KEYS;
|
|
46
|
+
if (overflow > 0) {
|
|
47
|
+
nextUnused.splice(0, overflow);
|
|
48
|
+
overflow -= currentUnused.length;
|
|
49
|
+
}
|
|
50
|
+
for (let iteration = senderKey.iteration + 1; iteration <= targetIteration; iteration += 1) {
|
|
36
51
|
if (overflow > 0) {
|
|
37
|
-
|
|
38
|
-
overflow -= currentUnused.length;
|
|
52
|
+
overflow -= 1;
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
overflow -= 1;
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
nextUnused.push(messageKey);
|
|
46
|
-
}
|
|
47
|
-
const derived = await deriveSenderKeyMsgKeyFromState(iteration, chainState);
|
|
48
|
-
chainState = derived.nextState;
|
|
49
|
-
messageKey = derived.messageKey;
|
|
54
|
+
else {
|
|
55
|
+
nextUnused.push(messageKey);
|
|
50
56
|
}
|
|
57
|
+
const derived = await deriveSenderKeyMsgKeyFromState(iteration, chainState);
|
|
58
|
+
chainState = derived.nextState;
|
|
59
|
+
messageKey = derived.messageKey;
|
|
51
60
|
}
|
|
52
61
|
return {
|
|
53
62
|
messageKey,
|
|
@@ -68,20 +77,16 @@ async function deriveSenderKeyMsgKey(iteration, chainKey) {
|
|
|
68
77
|
};
|
|
69
78
|
}
|
|
70
79
|
async function createSenderChainState(chainKey) {
|
|
71
|
-
|
|
72
|
-
throw new Error('sender key chainKey must be 32 bytes');
|
|
73
|
-
}
|
|
80
|
+
(0, bytes_1.assertByteLength)(chainKey, 32, 'sender key chainKey must be 32 bytes');
|
|
74
81
|
return {
|
|
75
82
|
chainKey,
|
|
76
83
|
hmacKey: await (0, _crypto_1.importHmacKey)(chainKey)
|
|
77
84
|
};
|
|
78
85
|
}
|
|
79
86
|
async function deriveSenderKeyMsgKeyFromState(iteration, state) {
|
|
80
|
-
const nextChainRawPromise = (0, _crypto_1.hmacSign)(state.hmacKey, constants_1.CHAIN_KEY_LABEL);
|
|
81
|
-
const messageInputKeyPromise = (0, _crypto_1.hmacSign)(state.hmacKey, constants_1.MESSAGE_KEY_LABEL);
|
|
82
87
|
const [nextChainRaw, messageInputKey] = await Promise.all([
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
(0, _crypto_1.hmacSign)(state.hmacKey, constants_1.CHAIN_KEY_LABEL),
|
|
89
|
+
(0, _crypto_1.hmacSign)(state.hmacKey, constants_1.MESSAGE_KEY_LABEL)
|
|
85
90
|
]);
|
|
86
91
|
const nextChainKey = nextChainRaw.subarray(0, 32);
|
|
87
92
|
const [nextHmacKey, messageSeed] = await Promise.all([
|
|
@@ -20,9 +20,7 @@ function parseDistributionPayload(payload) {
|
|
|
20
20
|
throw new Error('invalid sender key distribution message');
|
|
21
21
|
}
|
|
22
22
|
const chainKey = (0, bytes_1.toBytesView)(decoded.chainKey);
|
|
23
|
-
|
|
24
|
-
throw new Error('sender key distribution chainKey must be 32 bytes');
|
|
25
|
-
}
|
|
23
|
+
(0, bytes_1.assertByteLength)(chainKey, 32, 'sender key distribution chainKey must be 32 bytes');
|
|
26
24
|
return {
|
|
27
25
|
keyId: decoded.id,
|
|
28
26
|
iteration: decoded.iteration,
|
|
@@ -66,12 +66,16 @@ class SenderKeyManager {
|
|
|
66
66
|
}
|
|
67
67
|
const senderKey = await this.ensureSenderKey(groupId, sender);
|
|
68
68
|
const timestampMs = Date.now();
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
const distributions = new Array(participants.length);
|
|
70
|
+
for (let index = 0; index < participants.length; index += 1) {
|
|
71
|
+
distributions[index] = {
|
|
72
|
+
groupId,
|
|
73
|
+
sender: participants[index],
|
|
74
|
+
keyId: senderKey.keyId,
|
|
75
|
+
timestampMs
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
await this.store.upsertSenderKeyDistributions(distributions);
|
|
75
79
|
}
|
|
76
80
|
async processSenderKeyDistributionPayload(groupId, sender, payload) {
|
|
77
81
|
if (groupId.length === 0) {
|
|
@@ -87,13 +91,15 @@ class SenderKeyManager {
|
|
|
87
91
|
signingPublicKey: parsed.signingPublicKey,
|
|
88
92
|
unusedMessageKeys: []
|
|
89
93
|
};
|
|
90
|
-
await
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
await Promise.all([
|
|
95
|
+
this.store.upsertSenderKey(record),
|
|
96
|
+
this.store.upsertSenderKeyDistribution({
|
|
97
|
+
groupId,
|
|
98
|
+
sender,
|
|
99
|
+
keyId: parsed.keyId,
|
|
100
|
+
timestampMs: Date.now()
|
|
101
|
+
})
|
|
102
|
+
]);
|
|
97
103
|
return record;
|
|
98
104
|
}
|
|
99
105
|
async encryptGroupMessage(groupId, sender, plaintext) {
|
|
@@ -162,13 +168,17 @@ class SenderKeyManager {
|
|
|
162
168
|
if (existing) {
|
|
163
169
|
return existing;
|
|
164
170
|
}
|
|
165
|
-
const signingKeyPair = await
|
|
171
|
+
const [signingKeyPair, keyId, chainKey] = await Promise.all([
|
|
172
|
+
_crypto_1.X25519.generateKeyPair(),
|
|
173
|
+
(0, _crypto_1.randomIntAsync)(1, 2147483647),
|
|
174
|
+
(0, _crypto_1.randomBytesAsync)(32)
|
|
175
|
+
]);
|
|
166
176
|
const created = {
|
|
167
177
|
groupId,
|
|
168
178
|
sender,
|
|
169
|
-
keyId
|
|
179
|
+
keyId,
|
|
170
180
|
iteration: 0,
|
|
171
|
-
chainKey
|
|
181
|
+
chainKey,
|
|
172
182
|
signingPublicKey: (0, _crypto_1.toSerializedPubKey)(signingKeyPair.pubKey),
|
|
173
183
|
signingPrivateKey: signingKeyPair.privKey,
|
|
174
184
|
unusedMessageKeys: []
|
package/dist/signal/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SignalProtocol = exports.createAndStoreInitialKeys = exports.SenderKeyManager = exports.SignalSessionSyncApi = exports.SignalRotateKeyApi = exports.SignalMissingPreKeysSyncApi = exports.SignalIdentitySyncApi = exports.SignalDeviceSyncApi = exports.SignalDigestSyncApi = exports.parsePreKeyUploadFailure = exports.buildPreKeyUploadIq = exports.generateSignedPreKey = exports.generateRegistrationInfo = exports.generateRegistrationId = exports.generatePreKeyPair = void 0;
|
|
3
|
+
exports.createSignalSessionResolver = exports.SignalProtocol = exports.createAndStoreInitialKeys = exports.SenderKeyManager = exports.SignalSessionSyncApi = exports.SignalRotateKeyApi = exports.SignalMissingPreKeysSyncApi = exports.SignalIdentitySyncApi = exports.SignalDeviceSyncApi = exports.SignalDigestSyncApi = exports.parsePreKeyUploadFailure = exports.buildPreKeyUploadIq = exports.generateSignedPreKey = exports.generateRegistrationInfo = exports.generateRegistrationId = exports.generatePreKeyPair = void 0;
|
|
4
4
|
var keygen_1 = require("./registration/keygen");
|
|
5
5
|
Object.defineProperty(exports, "generatePreKeyPair", { enumerable: true, get: function () { return keygen_1.generatePreKeyPair; } });
|
|
6
6
|
Object.defineProperty(exports, "generateRegistrationId", { enumerable: true, get: function () { return keygen_1.generateRegistrationId; } });
|
|
@@ -27,3 +27,5 @@ var utils_1 = require("./registration/utils");
|
|
|
27
27
|
Object.defineProperty(exports, "createAndStoreInitialKeys", { enumerable: true, get: function () { return utils_1.createAndStoreInitialKeys; } });
|
|
28
28
|
var SignalProtocol_1 = require("./session/SignalProtocol");
|
|
29
29
|
Object.defineProperty(exports, "SignalProtocol", { enumerable: true, get: function () { return SignalProtocol_1.SignalProtocol; } });
|
|
30
|
+
var resolver_1 = require("./session/resolver");
|
|
31
|
+
Object.defineProperty(exports, "createSignalSessionResolver", { enumerable: true, get: function () { return resolver_1.createSignalSessionResolver; } });
|
|
@@ -8,6 +8,9 @@ const SignalRatchet_1 = require("../session/SignalRatchet");
|
|
|
8
8
|
const SignalSerializer_1 = require("../session/SignalSerializer");
|
|
9
9
|
const SignalSession_1 = require("../session/SignalSession");
|
|
10
10
|
const bytes_1 = require("../../util/bytes");
|
|
11
|
+
function signalAddressMapKey(address) {
|
|
12
|
+
return `${address.user}\u0001${address.server ?? ''}\u0001${address.device}`;
|
|
13
|
+
}
|
|
11
14
|
class SignalProtocol {
|
|
12
15
|
constructor(store, logger = new ConsoleLogger_1.ConsoleLogger('info')) {
|
|
13
16
|
this.store = store;
|
|
@@ -30,23 +33,55 @@ class SignalProtocol {
|
|
|
30
33
|
return session;
|
|
31
34
|
}
|
|
32
35
|
async encryptMessage(address, plaintext, expectedIdentity) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
const [encrypted] = await this.encryptMessagesBatch([
|
|
37
|
+
{ address, plaintext, expectedIdentity }
|
|
38
|
+
]);
|
|
39
|
+
return encrypted;
|
|
40
|
+
}
|
|
41
|
+
async encryptMessagesBatch(requests) {
|
|
42
|
+
if (requests.length === 0) {
|
|
43
|
+
return [];
|
|
36
44
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
const addresses = requests.map((request) => request.address);
|
|
46
|
+
const storedSessions = await this.store.getSessionsBatch(addresses);
|
|
47
|
+
const latestSessionByAddress = new Map();
|
|
48
|
+
const sessionUpdatesByAddress = new Map();
|
|
49
|
+
const identityUpdatesByAddress = new Map();
|
|
50
|
+
const results = new Array(requests.length);
|
|
51
|
+
for (let index = 0; index < requests.length; index += 1) {
|
|
52
|
+
const request = requests[index];
|
|
53
|
+
const address = request.address;
|
|
54
|
+
const addressKey = signalAddressMapKey(address);
|
|
55
|
+
const session = latestSessionByAddress.get(addressKey) ?? storedSessions[index];
|
|
56
|
+
if (!session) {
|
|
57
|
+
throw new Error('signal session not found');
|
|
58
|
+
}
|
|
59
|
+
if (request.expectedIdentity &&
|
|
60
|
+
!(0, bytes_1.uint8Equal)((0, _crypto_1.toSerializedPubKey)(request.expectedIdentity), session.remote.pubKey)) {
|
|
61
|
+
throw new Error('identity mismatch');
|
|
62
|
+
}
|
|
63
|
+
const [updatedSession, encrypted] = await (0, SignalRatchet_1.encryptMsg)(session, request.plaintext);
|
|
64
|
+
latestSessionByAddress.set(addressKey, updatedSession);
|
|
65
|
+
sessionUpdatesByAddress.set(addressKey, {
|
|
66
|
+
address,
|
|
67
|
+
session: updatedSession
|
|
68
|
+
});
|
|
69
|
+
if (!(0, bytes_1.uint8Equal)(updatedSession.remote.pubKey, session.remote.pubKey)) {
|
|
70
|
+
identityUpdatesByAddress.set(addressKey, {
|
|
71
|
+
address,
|
|
72
|
+
identityKey: updatedSession.remote.pubKey
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
results[index] = {
|
|
76
|
+
...encrypted,
|
|
77
|
+
baseKey: updatedSession.aliceBaseKey
|
|
78
|
+
};
|
|
40
79
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
await this.store.setRemoteIdentity(address, updatedSession.remote.pubKey);
|
|
80
|
+
await this.store.setSessionsBatch([...sessionUpdatesByAddress.values()]);
|
|
81
|
+
if (identityUpdatesByAddress.size > 0) {
|
|
82
|
+
await this.store.setRemoteIdentities([...identityUpdatesByAddress.values()]);
|
|
45
83
|
}
|
|
46
|
-
return
|
|
47
|
-
...encrypted,
|
|
48
|
-
baseKey: updatedSession.aliceBaseKey
|
|
49
|
-
};
|
|
84
|
+
return results;
|
|
50
85
|
}
|
|
51
86
|
async decryptMessage(address, envelope) {
|
|
52
87
|
const currentSession = await this.store.getSession(address);
|
|
@@ -59,24 +59,33 @@ async function selectMessageKey(chain, targetCounter) {
|
|
|
59
59
|
const first = await deriveMsgKeyFromState(chain.nextMsgIndex, chainState);
|
|
60
60
|
let currentMessageKey = first.messageKey;
|
|
61
61
|
chainState = first.nextState;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
if (delta === 0) {
|
|
63
|
+
return {
|
|
64
|
+
messageKey: currentMessageKey,
|
|
65
|
+
updatedChain: {
|
|
66
|
+
ratchetPubKey: chain.ratchetPubKey,
|
|
67
|
+
nextMsgIndex: targetCounter + 1,
|
|
68
|
+
chainKey: chainState.chainKey,
|
|
69
|
+
unusedMsgKeys: unused
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const nextUnused = unused.slice();
|
|
74
|
+
let overflow = delta + unused.length - constants_1.MAX_UNUSED_KEYS;
|
|
75
|
+
if (overflow > 0) {
|
|
76
|
+
nextUnused.splice(0, overflow);
|
|
77
|
+
overflow -= unused.length;
|
|
78
|
+
}
|
|
79
|
+
for (let counter = chain.nextMsgIndex + 1; counter <= targetCounter; counter += 1) {
|
|
65
80
|
if (overflow > 0) {
|
|
66
|
-
|
|
67
|
-
overflow -= unused.length;
|
|
81
|
+
overflow -= 1;
|
|
68
82
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
overflow -= 1;
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
nextUnused.push(currentMessageKey);
|
|
75
|
-
}
|
|
76
|
-
const derived = await deriveMsgKeyFromState(counter, chainState);
|
|
77
|
-
currentMessageKey = derived.messageKey;
|
|
78
|
-
chainState = derived.nextState;
|
|
83
|
+
else {
|
|
84
|
+
nextUnused.push(currentMessageKey);
|
|
79
85
|
}
|
|
86
|
+
const derived = await deriveMsgKeyFromState(counter, chainState);
|
|
87
|
+
currentMessageKey = derived.messageKey;
|
|
88
|
+
chainState = derived.nextState;
|
|
80
89
|
}
|
|
81
90
|
return {
|
|
82
91
|
messageKey: currentMessageKey,
|
|
@@ -32,16 +32,21 @@ function findMatchingSession(session, sessionBaseKey) {
|
|
|
32
32
|
if (session.aliceBaseKey && (0, bytes_1.uint8Equal)(session.aliceBaseKey, serializedBaseKey)) {
|
|
33
33
|
return session;
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
for (let index = 0; index < session.prevSessions.length; index += 1) {
|
|
36
|
+
const previousSession = session.prevSessions[index];
|
|
37
|
+
if (!previousSession.aliceBaseKey ||
|
|
38
|
+
!(0, bytes_1.uint8Equal)(previousSession.aliceBaseKey, serializedBaseKey)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const prevSessions = [detachSession(session)];
|
|
42
|
+
for (let i = 0; i < session.prevSessions.length; i += 1) {
|
|
43
|
+
if (i !== index) {
|
|
44
|
+
prevSessions.push(session.prevSessions[i]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
38
47
|
return {
|
|
39
|
-
...
|
|
40
|
-
prevSessions
|
|
41
|
-
detachSession(session),
|
|
42
|
-
...session.prevSessions.slice(0, previousSessionIndex),
|
|
43
|
-
...session.prevSessions.slice(previousSessionIndex + 1)
|
|
44
|
-
]
|
|
48
|
+
...previousSession,
|
|
49
|
+
prevSessions
|
|
45
50
|
};
|
|
46
51
|
}
|
|
47
52
|
return null;
|