zapo-js 0.2.0 → 0.3.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/README.md +7 -3
- package/dist/appstate/WaAppStateCrypto.js +49 -41
- package/dist/appstate/WaAppStateSyncClient.js +79 -42
- package/dist/appstate/index.js +2 -2
- package/dist/auth/WaAuthClient.js +20 -11
- package/dist/auth/{flow/WaAuthCredentialsFlow.js → credentials-flow.js} +83 -18
- package/dist/auth/pairing/WaPairingFlow.js +26 -29
- package/dist/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +29 -13
- package/dist/client/WaClient.js +115 -75
- package/dist/client/WaClientFactory.js +113 -30
- package/dist/client/connection/WaConnectionManager.js +4 -1
- package/dist/client/coordinators/WaAbPropsCoordinator.js +141 -0
- package/dist/client/coordinators/WaBusinessCoordinator.js +3 -12
- package/dist/client/coordinators/WaEmailCoordinator.js +63 -0
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +33 -8
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +55 -25
- package/dist/client/coordinators/WaOfflineResumeCoordinator.js +114 -0
- package/dist/client/coordinators/WaPassiveTasksCoordinator.js +38 -20
- package/dist/client/coordinators/WaProfileCoordinator.js +3 -1
- package/dist/client/coordinators/WaRetryCoordinator.js +11 -9
- package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +22 -4
- package/dist/client/dirty.js +1 -1
- package/dist/client/events/abprops.js +43 -0
- package/dist/client/events/privacy-token.js +1 -2
- package/dist/client/events/registration.js +42 -0
- package/dist/client/incoming.js +37 -0
- package/dist/client/mailbox.js +17 -1
- package/dist/client/media.js +243 -0
- package/dist/client/messages.js +163 -86
- package/dist/crypto/core/index.js +4 -1
- package/dist/crypto/core/random.js +3 -9
- package/dist/crypto/core/xeddsa.js +57 -0
- package/dist/crypto/curves/X25519.js +18 -0
- package/dist/crypto/curves/constants.js +2 -1
- package/dist/esm/appstate/WaAppStateCrypto.js +39 -31
- package/dist/esm/appstate/WaAppStateSyncClient.js +68 -31
- package/dist/esm/appstate/index.js +1 -1
- package/dist/esm/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +1 -1
- package/dist/esm/auth/WaAuthClient.js +17 -8
- package/dist/esm/auth/{flow/WaAuthCredentialsFlow.js → credentials-flow.js} +83 -18
- package/dist/esm/auth/pairing/WaPairingFlow.js +25 -28
- package/dist/esm/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +20 -6
- package/dist/esm/client/WaClient.js +116 -76
- package/dist/esm/client/WaClientFactory.js +114 -31
- package/dist/esm/client/connection/WaConnectionManager.js +4 -1
- package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +137 -0
- package/dist/esm/client/coordinators/WaBusinessCoordinator.js +4 -13
- package/dist/esm/client/coordinators/WaEmailCoordinator.js +60 -0
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +35 -10
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +47 -17
- package/dist/esm/client/coordinators/WaOfflineResumeCoordinator.js +110 -0
- package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +38 -20
- package/dist/esm/client/coordinators/WaProfileCoordinator.js +3 -1
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +11 -9
- package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +24 -6
- package/dist/esm/client/dirty.js +1 -1
- package/dist/esm/client/events/abprops.js +40 -0
- package/dist/esm/client/events/privacy-token.js +1 -2
- package/dist/esm/client/events/registration.js +39 -0
- package/dist/esm/client/incoming.js +36 -0
- package/dist/esm/client/mailbox.js +17 -1
- package/dist/esm/client/media.js +234 -0
- package/dist/esm/client/messages.js +162 -85
- package/dist/esm/crypto/core/index.js +1 -0
- package/dist/esm/crypto/core/random.js +2 -7
- package/dist/esm/crypto/core/xeddsa.js +53 -0
- package/dist/esm/crypto/curves/X25519.js +20 -2
- package/dist/esm/crypto/curves/constants.js +1 -0
- package/dist/esm/infra/perf/StoreLock.js +7 -4
- package/dist/esm/media/WaMediaCrypto.js +257 -62
- package/dist/esm/media/WaMediaTransferClient.js +47 -190
- package/dist/esm/media/constants.js +2 -0
- package/dist/esm/media/processor.js +1 -0
- package/dist/esm/message/addon-crypto.js +130 -3
- package/dist/esm/message/content.js +12 -6
- package/dist/esm/message/icdc.js +8 -8
- package/dist/esm/message/incoming.js +14 -12
- package/dist/esm/message/phash.js +32 -12
- package/dist/esm/message/reporting-token.js +3 -3
- package/dist/esm/message/use-case-secret.js +1 -1
- package/dist/esm/protocol/abprops.js +159 -0
- package/dist/esm/protocol/browser.js +14 -0
- package/dist/esm/protocol/constants.js +3 -1
- package/dist/esm/protocol/email.js +30 -0
- package/dist/esm/protocol/jid.js +44 -10
- package/dist/esm/protocol/nodes.js +6 -2
- package/dist/esm/protocol/notification.js +7 -1
- package/dist/esm/retry/reason.js +1 -1
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +5 -2
- package/dist/esm/signal/api/SignalDigestSyncApi.js +8 -6
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +4 -4
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +1 -1
- package/dist/esm/signal/api/SignalSessionSyncApi.js +1 -1
- package/dist/esm/signal/crypto/WaAdvSignature.js +5 -51
- package/dist/esm/signal/crypto/constants.js +0 -4
- package/dist/esm/signal/encoding.js +11 -54
- package/dist/esm/signal/group/SenderKeyChain.js +3 -3
- package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
- package/dist/esm/signal/group/SenderKeyManager.js +13 -10
- package/dist/esm/signal/registration/keygen.js +2 -3
- package/dist/esm/signal/registration/utils.js +2 -2
- package/dist/esm/signal/session/SignalProtocol.js +18 -17
- package/dist/esm/signal/session/SignalRatchet.js +21 -10
- package/dist/esm/signal/session/SignalSerializer.js +5 -6
- package/dist/esm/signal/session/SignalSession.js +11 -9
- package/dist/esm/signal/session/resolver.js +6 -6
- package/dist/esm/store/contracts/identity.store.js +1 -0
- package/dist/esm/store/contracts/message-secret.store.js +1 -0
- package/dist/esm/store/contracts/pre-key.store.js +1 -0
- package/dist/esm/store/contracts/session.store.js +1 -0
- package/dist/esm/store/createStore.js +48 -12
- package/dist/esm/store/index.js +4 -0
- package/dist/esm/store/locks/identity.lock.js +16 -0
- package/dist/esm/store/locks/message-secret.lock.js +17 -0
- package/dist/esm/store/locks/pre-key.lock.js +27 -0
- package/dist/esm/store/locks/session.lock.js +19 -0
- package/dist/esm/store/locks/signal.lock.js +0 -24
- package/dist/esm/store/noop.store.js +20 -0
- package/dist/esm/store/providers/memory/device-list.store.js +3 -0
- package/dist/esm/store/providers/memory/identity.store.js +31 -0
- package/dist/esm/store/providers/memory/message-secret.store.js +81 -0
- package/dist/esm/store/providers/memory/participants.store.js +3 -0
- package/dist/esm/store/providers/memory/pre-key.store.js +97 -0
- package/dist/esm/store/providers/memory/retry.store.js +25 -11
- package/dist/esm/store/providers/memory/session.store.js +45 -0
- package/dist/esm/store/providers/memory/signal.store.js +1 -164
- package/dist/esm/transport/WaComms.js +4 -3
- package/dist/esm/transport/WaWebSocket.js +9 -1
- package/dist/esm/transport/index.js +6 -0
- package/dist/esm/transport/keepalive/WaKeepAlive.js +17 -8
- package/dist/esm/transport/node/WaMobileTcpSocket.js +114 -0
- package/dist/esm/transport/node/WaNodeOrchestrator.js +17 -8
- package/dist/esm/transport/node/builders/abprops.js +20 -0
- package/dist/esm/transport/node/builders/device.js +11 -0
- package/dist/esm/transport/node/builders/email.js +65 -0
- package/dist/esm/transport/node/builders/offline.js +14 -0
- package/dist/esm/transport/node/builders/prekeys.js +37 -40
- package/dist/esm/transport/node/builders/presence.js +13 -0
- package/dist/esm/transport/node/builders/privacy-token.js +19 -23
- package/dist/esm/transport/node/builders/retry.js +1 -1
- package/dist/esm/transport/node/helpers.js +24 -0
- package/dist/esm/transport/node/mex/argo-decoder.js +152 -0
- package/dist/esm/transport/node/mex/client.js +83 -0
- package/dist/esm/transport/node/mex/persist-ids.js +10 -0
- package/dist/esm/transport/noise/WaClientPayload.js +15 -10
- package/dist/esm/transport/noise/WaFrameCodec.js +2 -2
- package/dist/esm/transport/noise/WaMobileClientPayload.js +53 -0
- package/dist/esm/transport/noise/WaNoiseCert.js +9 -27
- package/dist/esm/transport/noise/WaNoiseSession.js +12 -11
- package/dist/infra/perf/StoreLock.js +7 -4
- package/dist/media/WaMediaCrypto.js +253 -58
- package/dist/media/WaMediaTransferClient.js +50 -223
- package/dist/media/constants.js +3 -1
- package/dist/media/processor.js +2 -0
- package/dist/message/addon-crypto.js +131 -0
- package/dist/message/content.js +13 -5
- package/dist/message/icdc.js +8 -8
- package/dist/message/incoming.js +14 -12
- package/dist/message/phash.js +32 -12
- package/dist/message/reporting-token.js +2 -2
- package/dist/message/use-case-secret.js +1 -1
- package/dist/protocol/abprops.js +163 -0
- package/dist/protocol/browser.js +15 -0
- package/dist/protocol/constants.js +14 -2
- package/dist/protocol/email.js +33 -0
- package/dist/protocol/jid.js +45 -10
- package/dist/protocol/nodes.js +6 -2
- package/dist/protocol/notification.js +8 -2
- package/dist/retry/reason.js +1 -1
- package/dist/signal/api/SignalDeviceSyncApi.js +5 -2
- package/dist/signal/api/SignalDigestSyncApi.js +8 -6
- package/dist/signal/api/SignalIdentitySyncApi.js +4 -4
- package/dist/signal/crypto/WaAdvSignature.js +2 -50
- package/dist/signal/crypto/constants.js +1 -5
- package/dist/signal/encoding.js +11 -49
- package/dist/signal/group/SenderKeyChain.js +2 -2
- package/dist/signal/group/SenderKeyCodec.js +4 -5
- package/dist/signal/group/SenderKeyManager.js +12 -9
- package/dist/signal/registration/keygen.js +1 -2
- package/dist/signal/registration/utils.js +2 -2
- package/dist/signal/session/SignalProtocol.js +18 -17
- package/dist/signal/session/SignalRatchet.js +19 -8
- package/dist/signal/session/SignalSerializer.js +5 -6
- package/dist/signal/session/SignalSession.js +11 -9
- package/dist/signal/session/resolver.js +6 -6
- package/dist/store/contracts/identity.store.js +2 -0
- package/dist/store/contracts/message-secret.store.js +2 -0
- package/dist/store/contracts/pre-key.store.js +2 -0
- package/dist/store/contracts/session.store.js +2 -0
- package/dist/store/createStore.js +47 -11
- package/dist/store/index.js +9 -1
- package/dist/store/locks/identity.lock.js +19 -0
- package/dist/store/locks/message-secret.lock.js +20 -0
- package/dist/store/locks/pre-key.lock.js +30 -0
- package/dist/store/locks/session.lock.js +22 -0
- package/dist/store/locks/signal.lock.js +0 -24
- package/dist/store/noop.store.js +21 -1
- package/dist/store/providers/memory/device-list.store.js +3 -0
- package/dist/store/providers/memory/identity.store.js +35 -0
- package/dist/store/providers/memory/message-secret.store.js +85 -0
- package/dist/store/providers/memory/participants.store.js +3 -0
- package/dist/store/providers/memory/pre-key.store.js +101 -0
- package/dist/store/providers/memory/retry.store.js +24 -10
- package/dist/store/providers/memory/session.store.js +49 -0
- package/dist/store/providers/memory/signal.store.js +1 -164
- package/dist/transport/WaComms.js +4 -3
- package/dist/transport/WaWebSocket.js +9 -1
- package/dist/transport/index.js +17 -1
- package/dist/transport/keepalive/WaKeepAlive.js +17 -8
- package/dist/transport/node/WaMobileTcpSocket.js +118 -0
- package/dist/transport/node/WaNodeOrchestrator.js +16 -7
- package/dist/transport/node/builders/abprops.js +23 -0
- package/dist/transport/node/builders/device.js +14 -0
- package/dist/transport/node/builders/email.js +72 -0
- package/dist/transport/node/builders/offline.js +17 -0
- package/dist/transport/node/builders/prekeys.js +36 -39
- package/dist/transport/node/builders/presence.js +16 -0
- package/dist/transport/node/builders/privacy-token.js +18 -22
- package/dist/transport/node/builders/retry.js +1 -1
- package/dist/transport/node/helpers.js +26 -0
- package/dist/transport/node/mex/argo-decoder.js +189 -0
- package/dist/transport/node/mex/client.js +86 -0
- package/dist/transport/node/mex/persist-ids.js +13 -0
- package/dist/transport/noise/WaClientPayload.js +14 -9
- package/dist/transport/noise/WaFrameCodec.js +1 -1
- package/dist/transport/noise/WaMobileClientPayload.js +56 -0
- package/dist/transport/noise/WaNoiseCert.js +8 -26
- package/dist/transport/noise/WaNoiseSession.js +11 -10
- package/dist/types/appstate/WaAppStateCrypto.d.ts +11 -8
- package/dist/types/appstate/WaAppStateSyncClient.d.ts +6 -2
- package/dist/types/appstate/index.d.ts +1 -1
- package/dist/types/appstate/{WaAppStateSyncResponseParser.d.ts → response-parser.d.ts} +1 -1
- package/dist/types/appstate/types.d.ts +1 -1
- package/dist/types/auth/WaAuthClient.d.ts +9 -3
- package/dist/types/auth/credentials-flow.d.ts +20 -0
- package/dist/types/auth/pairing/WaPairingFlow.d.ts +3 -2
- package/dist/types/auth/pairing/{WaPairingCodeCrypto.d.ts → pairing-code-crypto.d.ts} +6 -1
- package/dist/types/auth/types.d.ts +40 -0
- package/dist/types/client/WaClient.d.ts +19 -8
- package/dist/types/client/WaClientFactory.d.ts +10 -4
- package/dist/types/client/coordinators/WaAbPropsCoordinator.d.ts +26 -0
- package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +1 -1
- package/dist/types/client/coordinators/WaEmailCoordinator.d.ts +24 -0
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +6 -1
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +15 -2
- package/dist/types/client/coordinators/WaOfflineResumeCoordinator.d.ts +31 -0
- package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +13 -2
- package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +1 -1
- package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +4 -2
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +6 -0
- package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +11 -1
- package/dist/types/client/dirty.d.ts +3 -1
- package/dist/types/client/events/abprops.d.ts +14 -0
- package/dist/types/client/events/registration.d.ts +17 -0
- package/dist/types/client/incoming.d.ts +6 -1
- package/dist/types/client/mailbox.d.ts +2 -0
- package/dist/types/client/media.d.ts +31 -0
- package/dist/types/client/messages.d.ts +2 -0
- package/dist/types/client/persistence/WriteBehindPersistence.d.ts +1 -1
- package/dist/types/client/types.d.ts +100 -1
- package/dist/types/crypto/core/index.d.ts +1 -0
- package/dist/types/crypto/core/primitives.d.ts +1 -1
- package/dist/types/crypto/core/random.d.ts +1 -1
- package/dist/types/crypto/core/xeddsa.d.ts +2 -0
- package/dist/types/crypto/curves/constants.d.ts +1 -0
- package/dist/types/crypto/index.d.ts +1 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/infra/log/ConsoleLogger.d.ts +1 -1
- package/dist/types/infra/log/PinoLogger.d.ts +1 -1
- package/dist/types/infra/perf/StoreLock.d.ts +1 -0
- package/dist/types/media/WaMediaCrypto.d.ts +15 -6
- package/dist/types/media/WaMediaTransferClient.d.ts +3 -11
- package/dist/types/media/constants.d.ts +2 -0
- package/dist/types/media/index.d.ts +1 -0
- package/dist/types/media/processor.d.ts +28 -0
- package/dist/types/media/types.d.ts +9 -3
- package/dist/types/message/addon-crypto.d.ts +34 -3
- package/dist/types/message/content.d.ts +3 -1
- package/dist/types/message/icdc.d.ts +4 -4
- package/dist/types/message/types.d.ts +16 -24
- package/dist/types/protocol/abprops.d.ts +142 -0
- package/dist/types/protocol/browser.d.ts +1 -0
- package/dist/types/protocol/constants.d.ts +5 -1
- package/dist/types/protocol/email.d.ts +32 -0
- package/dist/types/protocol/jid.d.ts +1 -0
- package/dist/types/protocol/nodes.d.ts +4 -0
- package/dist/types/protocol/notification.d.ts +6 -0
- package/dist/types/protocol/stream.d.ts +1 -0
- package/dist/types/retry/reason.d.ts +1 -1
- package/dist/types/signal/api/SignalDigestSyncApi.d.ts +3 -0
- package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +3 -3
- package/dist/types/signal/crypto/WaAdvSignature.d.ts +0 -2
- package/dist/types/signal/crypto/constants.d.ts +0 -1
- package/dist/types/signal/encoding.d.ts +7 -1
- package/dist/types/signal/group/SenderKeyChain.d.ts +1 -1
- package/dist/types/signal/group/SenderKeyManager.d.ts +7 -2
- package/dist/types/signal/registration/utils.d.ts +2 -1
- package/dist/types/signal/session/SignalProtocol.d.ts +11 -2
- package/dist/types/signal/session/SignalSerializer.d.ts +2 -1
- package/dist/types/signal/session/resolver.d.ts +4 -2
- package/dist/types/signal/types.d.ts +16 -4
- package/dist/types/store/contracts/identity.store.d.ts +11 -0
- package/dist/types/store/contracts/message-secret.store.d.ts +16 -0
- package/dist/types/store/contracts/pre-key.store.d.ts +13 -0
- package/dist/types/store/contracts/session.store.d.ts +14 -0
- package/dist/types/store/contracts/signal.store.d.ts +1 -34
- package/dist/types/store/index.d.ts +9 -1
- package/dist/types/store/locks/identity.lock.d.ts +3 -0
- package/dist/types/store/locks/message-secret.lock.d.ts +3 -0
- package/dist/types/store/locks/pre-key.lock.d.ts +3 -0
- package/dist/types/store/locks/session.lock.d.ts +3 -0
- package/dist/types/store/noop.store.d.ts +4 -0
- package/dist/types/store/providers/memory/identity.store.d.ts +18 -0
- package/dist/types/store/providers/memory/message-secret.store.d.ts +21 -0
- package/dist/types/store/providers/memory/pre-key.store.d.ts +23 -0
- package/dist/types/store/providers/memory/retry.store.d.ts +7 -1
- package/dist/types/store/providers/memory/session.store.d.ts +21 -0
- package/dist/types/store/providers/memory/signal.store.d.ts +3 -45
- package/dist/types/store/providers/memory/thread.store.d.ts +1 -1
- package/dist/types/store/types.d.ts +21 -1
- package/dist/types/transport/WaWebSocket.d.ts +1 -0
- package/dist/types/transport/index.d.ts +8 -1
- package/dist/types/transport/keepalive/WaKeepAlive.d.ts +4 -1
- package/dist/types/transport/node/WaMobileTcpSocket.d.ts +18 -0
- package/dist/types/transport/node/WaNodeOrchestrator.d.ts +6 -2
- package/dist/types/transport/node/builders/abprops.d.ts +5 -0
- package/dist/types/transport/node/builders/device.d.ts +2 -0
- package/dist/types/transport/node/builders/email.d.ts +11 -0
- package/dist/types/transport/node/builders/offline.d.ts +2 -0
- package/dist/types/transport/node/builders/prekeys.d.ts +4 -3
- package/dist/types/transport/node/builders/presence.d.ts +6 -0
- package/dist/types/transport/node/helpers.d.ts +3 -0
- package/dist/types/transport/node/mex/argo-decoder.d.ts +11 -0
- package/dist/types/transport/node/mex/client.d.ts +18 -0
- package/dist/types/transport/node/mex/persist-ids.d.ts +14 -0
- package/dist/types/transport/noise/WaMobileClientPayload.d.ts +29 -0
- package/dist/types/transport/noise/WaNoiseCert.d.ts +7 -1
- package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -0
- package/dist/types/transport/types.d.ts +8 -0
- package/package.json +6 -4
- package/dist/auth/pairing/constants.js +0 -5
- package/dist/client/connection/WaKeyShareCoordinator.js +0 -63
- package/dist/esm/auth/pairing/constants.js +0 -2
- package/dist/esm/client/connection/WaKeyShareCoordinator.js +0 -59
- package/dist/esm/transport/node/builders/index.js +0 -11
- package/dist/transport/node/builders/index.js +0 -51
- package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +0 -14
- package/dist/types/auth/pairing/constants.d.ts +0 -2
- package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +0 -14
- package/dist/types/transport/node/builders/index.d.ts +0 -11
- /package/dist/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +0 -0
package/dist/client/messages.js
CHANGED
|
@@ -3,12 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.buildMediaMessageContent = buildMediaMessageContent;
|
|
4
4
|
exports.getMediaConn = getMediaConn;
|
|
5
5
|
const node_fs_1 = require("node:fs");
|
|
6
|
+
const media_1 = require("./media");
|
|
6
7
|
const conn_1 = require("../media/conn");
|
|
7
8
|
const constants_1 = require("../media/constants");
|
|
8
9
|
const WaMediaCrypto_1 = require("../media/WaMediaCrypto");
|
|
9
10
|
const content_1 = require("../message/content");
|
|
10
11
|
const constants_2 = require("../protocol/constants");
|
|
11
|
-
const
|
|
12
|
+
const media_2 = require("../transport/node/builders/media");
|
|
12
13
|
const bytes_1 = require("../util/bytes");
|
|
13
14
|
const primitives_1 = require("../util/primitives");
|
|
14
15
|
async function buildMediaMessageContent(options, content) {
|
|
@@ -30,11 +31,14 @@ async function getMediaConn(options, forceRefresh = false) {
|
|
|
30
31
|
if (!forceRefresh && cached && Date.now() + constants_1.MEDIA_CONN_CACHE_GRACE_MS < cached.expiresAtMs) {
|
|
31
32
|
return cached;
|
|
32
33
|
}
|
|
33
|
-
const response = await options.queryWithContext('media_conn.fetch', (0,
|
|
34
|
+
const response = await options.queryWithContext('media_conn.fetch', (0, media_2.buildMediaConnIq)(), options.iqTimeoutMs ?? constants_2.WA_DEFAULTS.IQ_TIMEOUT_MS);
|
|
34
35
|
const mediaConn = (0, conn_1.parseMediaConnResponse)(response, Date.now());
|
|
35
36
|
options.setMediaConnCache(mediaConn);
|
|
36
37
|
return mediaConn;
|
|
37
38
|
}
|
|
39
|
+
function needsSidecar(content) {
|
|
40
|
+
return content.type === 'video' || content.type === 'ptv' || content.type === 'audio';
|
|
41
|
+
}
|
|
38
42
|
function resolveUploadType(content) {
|
|
39
43
|
if (content.type === 'video' && content.gifPlayback)
|
|
40
44
|
return 'gif';
|
|
@@ -42,85 +46,146 @@ function resolveUploadType(content) {
|
|
|
42
46
|
return 'ptt';
|
|
43
47
|
return content.type;
|
|
44
48
|
}
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
function resolveMimetype(content) {
|
|
50
|
+
if (content.mimetype)
|
|
51
|
+
return content.mimetype;
|
|
52
|
+
if (content.type === 'sticker')
|
|
53
|
+
return 'image/webp';
|
|
54
|
+
throw new Error(`mimetype is required for ${content.type} messages`);
|
|
50
55
|
}
|
|
51
56
|
async function buildMediaMessage(options, content) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
...common,
|
|
101
|
-
seconds: content.seconds,
|
|
102
|
-
ptt: content.ptt
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
case 'document':
|
|
106
|
-
return {
|
|
107
|
-
documentMessage: {
|
|
108
|
-
...common,
|
|
109
|
-
caption: content.caption,
|
|
110
|
-
fileName: content.fileName ?? 'file',
|
|
111
|
-
title: content.fileName ?? undefined
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
case 'sticker':
|
|
115
|
-
return {
|
|
116
|
-
stickerMessage: {
|
|
117
|
-
...common,
|
|
118
|
-
width: content.width,
|
|
119
|
-
height: content.height
|
|
57
|
+
const needsTempFile = (0, media_1.hasMediaProcessingTasks)(options.media, content) ||
|
|
58
|
+
(content.type === 'sticker' && content.firstFrameLength === undefined);
|
|
59
|
+
const resolved = await (0, media_1.resolveMediaInputs)(needsTempFile, content.media);
|
|
60
|
+
try {
|
|
61
|
+
let detectedFirstFrameLength;
|
|
62
|
+
if (content.type === 'sticker' &&
|
|
63
|
+
content.firstFrameLength === undefined &&
|
|
64
|
+
resolved.processorInput) {
|
|
65
|
+
const input = resolved.processorInput;
|
|
66
|
+
const header = typeof input === 'string' ? await (0, media_1.readFileHead)(input, 100) : input.subarray(0, 100);
|
|
67
|
+
detectedFirstFrameLength = (0, media_1.parseWebpAnimation)(header)?.firstFrameLength;
|
|
68
|
+
}
|
|
69
|
+
const firstFrameLength = content.type === 'sticker'
|
|
70
|
+
? (content.firstFrameLength ?? detectedFirstFrameLength)
|
|
71
|
+
: undefined;
|
|
72
|
+
const uploadPromise = (0, media_1.isReadableStream)(resolved.uploadMedia)
|
|
73
|
+
? uploadMediaStream(options, content, resolved.uploadMedia, firstFrameLength)
|
|
74
|
+
: uploadMediaBytes(options, content, resolved.uploadMedia, firstFrameLength);
|
|
75
|
+
const processPromise = (0, media_1.runMediaProcessor)(options.media, resolved.processorInput, content, options.logger);
|
|
76
|
+
const [uploadResult, processResult] = await Promise.allSettled([
|
|
77
|
+
uploadPromise,
|
|
78
|
+
processPromise
|
|
79
|
+
]);
|
|
80
|
+
if (uploadResult.status === 'rejected')
|
|
81
|
+
throw uploadResult.reason;
|
|
82
|
+
if (processResult.status === 'rejected')
|
|
83
|
+
throw processResult.reason;
|
|
84
|
+
const uploaded = uploadResult.value;
|
|
85
|
+
const processed = processResult.value;
|
|
86
|
+
const mediaKeyTimestamp = Math.floor(Date.now() / 1000);
|
|
87
|
+
const uploadedFields = {
|
|
88
|
+
url: uploaded.url,
|
|
89
|
+
fileSha256: uploaded.fileSha256,
|
|
90
|
+
fileLength: uploaded.fileLength,
|
|
91
|
+
mediaKey: uploaded.mediaKey,
|
|
92
|
+
fileEncSha256: uploaded.fileEncSha256,
|
|
93
|
+
directPath: uploaded.directPath,
|
|
94
|
+
mediaKeyTimestamp,
|
|
95
|
+
mimetype: resolveMimetype(content)
|
|
96
|
+
};
|
|
97
|
+
function spread(c) {
|
|
98
|
+
const result = {};
|
|
99
|
+
for (const key in c) {
|
|
100
|
+
if (key !== 'type' &&
|
|
101
|
+
key !== 'media' &&
|
|
102
|
+
key !== 'fileLength' &&
|
|
103
|
+
key !== 'mimetype') {
|
|
104
|
+
result[key] = c[key];
|
|
120
105
|
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
switch (content.type) {
|
|
110
|
+
case 'image':
|
|
111
|
+
return {
|
|
112
|
+
imageMessage: {
|
|
113
|
+
...spread(content),
|
|
114
|
+
...uploadedFields,
|
|
115
|
+
width: content.width ?? processed.width,
|
|
116
|
+
height: content.height ?? processed.height,
|
|
117
|
+
jpegThumbnail: content.jpegThumbnail ?? processed.jpegThumbnail
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
case 'video':
|
|
121
|
+
return {
|
|
122
|
+
videoMessage: {
|
|
123
|
+
...spread(content),
|
|
124
|
+
...uploadedFields,
|
|
125
|
+
seconds: content.seconds ?? processed.seconds,
|
|
126
|
+
width: content.width ?? processed.width,
|
|
127
|
+
height: content.height ?? processed.height,
|
|
128
|
+
jpegThumbnail: content.jpegThumbnail ?? processed.jpegThumbnail,
|
|
129
|
+
streamingSidecar: uploaded.streamingSidecar,
|
|
130
|
+
metadataUrl: uploaded.metadataUrl
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
case 'ptv':
|
|
134
|
+
return {
|
|
135
|
+
ptvMessage: {
|
|
136
|
+
...spread(content),
|
|
137
|
+
...uploadedFields,
|
|
138
|
+
seconds: content.seconds ?? processed.seconds,
|
|
139
|
+
width: content.width ?? processed.width,
|
|
140
|
+
height: content.height ?? processed.height,
|
|
141
|
+
jpegThumbnail: content.jpegThumbnail ?? processed.jpegThumbnail,
|
|
142
|
+
streamingSidecar: uploaded.streamingSidecar
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
case 'audio':
|
|
146
|
+
return {
|
|
147
|
+
audioMessage: {
|
|
148
|
+
...spread(content),
|
|
149
|
+
...uploadedFields,
|
|
150
|
+
seconds: content.seconds ?? processed.seconds,
|
|
151
|
+
streamingSidecar: uploaded.streamingSidecar,
|
|
152
|
+
waveform: content.waveform ?? processed.waveform
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
case 'document':
|
|
156
|
+
return {
|
|
157
|
+
documentMessage: {
|
|
158
|
+
...spread(content),
|
|
159
|
+
...uploadedFields,
|
|
160
|
+
fileName: content.fileName ?? 'file',
|
|
161
|
+
title: content.title ?? content.fileName ?? undefined,
|
|
162
|
+
jpegThumbnail: content.jpegThumbnail ?? processed.jpegThumbnail
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
case 'sticker':
|
|
166
|
+
return {
|
|
167
|
+
stickerMessage: {
|
|
168
|
+
...spread(content),
|
|
169
|
+
...uploadedFields,
|
|
170
|
+
width: content.width ?? processed.width,
|
|
171
|
+
height: content.height ?? processed.height,
|
|
172
|
+
pngThumbnail: content.pngThumbnail ?? processed.pngThumbnail,
|
|
173
|
+
isAnimated: content.isAnimated ??
|
|
174
|
+
processed.isAnimated ??
|
|
175
|
+
firstFrameLength !== undefined,
|
|
176
|
+
firstFrameLength: content.firstFrameLength ?? uploaded.firstFrameLength,
|
|
177
|
+
firstFrameSidecar: content.firstFrameSidecar ?? uploaded.firstFrameSidecar,
|
|
178
|
+
stickerSentTs: content.stickerSentTs ?? Date.now()
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
default:
|
|
182
|
+
throw new Error(`unsupported media message type: ${String(content.type)}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
if (resolved.tempFilePath) {
|
|
187
|
+
await (0, media_1.cleanupTempFile)(resolved.tempFilePath);
|
|
188
|
+
}
|
|
124
189
|
}
|
|
125
190
|
}
|
|
126
191
|
function buildUploadUrl(host, uploadType, auth, fileEncSha256) {
|
|
@@ -151,11 +216,14 @@ function parseUploadResponse(body, status) {
|
|
|
151
216
|
...(parsed.metadata_url ? { metadataUrl: parsed.metadata_url } : {})
|
|
152
217
|
};
|
|
153
218
|
}
|
|
154
|
-
async function uploadMediaBytes(options, content, mediaBytes) {
|
|
219
|
+
async function uploadMediaBytes(options, content, mediaBytes, firstFrameLength) {
|
|
155
220
|
const uploadType = resolveUploadType(content);
|
|
156
221
|
const mediaKey = await WaMediaCrypto_1.WaMediaCrypto.generateMediaKey();
|
|
157
222
|
const [encrypted, mediaConn] = await Promise.all([
|
|
158
|
-
WaMediaCrypto_1.WaMediaCrypto.encryptBytes(uploadType, mediaKey, mediaBytes
|
|
223
|
+
WaMediaCrypto_1.WaMediaCrypto.encryptBytes(uploadType, mediaKey, mediaBytes, {
|
|
224
|
+
sidecar: needsSidecar(content),
|
|
225
|
+
firstFrameLength
|
|
226
|
+
}),
|
|
159
227
|
getMediaConn(options)
|
|
160
228
|
]);
|
|
161
229
|
const selectedHost = mediaConn.hosts.find((host) => !host.isFallback)?.hostname ?? mediaConn.hosts[0].hostname;
|
|
@@ -170,7 +238,7 @@ async function uploadMediaBytes(options, content, mediaBytes) {
|
|
|
170
238
|
method: 'POST',
|
|
171
239
|
body: encrypted.ciphertextHmac,
|
|
172
240
|
contentLength: encrypted.ciphertextHmac.byteLength,
|
|
173
|
-
contentType: content
|
|
241
|
+
contentType: resolveMimetype(content)
|
|
174
242
|
});
|
|
175
243
|
const responseBody = await options.mediaTransfer.readResponseBytes(uploadResponse);
|
|
176
244
|
const parsed = parseUploadResponse(responseBody, uploadResponse.status);
|
|
@@ -179,13 +247,19 @@ async function uploadMediaBytes(options, content, mediaBytes) {
|
|
|
179
247
|
mediaKey,
|
|
180
248
|
fileSha256: encrypted.fileSha256,
|
|
181
249
|
fileEncSha256: encrypted.fileEncSha256,
|
|
182
|
-
fileLength: mediaBytes.byteLength
|
|
250
|
+
fileLength: mediaBytes.byteLength,
|
|
251
|
+
streamingSidecar: encrypted.streamingSidecar,
|
|
252
|
+
firstFrameSidecar: encrypted.firstFrameSidecar,
|
|
253
|
+
firstFrameLength
|
|
183
254
|
};
|
|
184
255
|
}
|
|
185
|
-
async function uploadMediaStream(options, content, stream) {
|
|
256
|
+
async function uploadMediaStream(options, content, stream, firstFrameLength) {
|
|
186
257
|
const uploadType = resolveUploadType(content);
|
|
187
258
|
const mediaKey = await WaMediaCrypto_1.WaMediaCrypto.generateMediaKey();
|
|
188
|
-
const encResult = await WaMediaCrypto_1.WaMediaCrypto.encryptToFile(uploadType, mediaKey, stream
|
|
259
|
+
const encResult = await WaMediaCrypto_1.WaMediaCrypto.encryptToFile(uploadType, mediaKey, stream, {
|
|
260
|
+
sidecar: needsSidecar(content),
|
|
261
|
+
firstFrameLength
|
|
262
|
+
});
|
|
189
263
|
let readStream;
|
|
190
264
|
try {
|
|
191
265
|
const mediaConn = await getMediaConn(options);
|
|
@@ -204,7 +278,7 @@ async function uploadMediaStream(options, content, stream) {
|
|
|
204
278
|
method: 'POST',
|
|
205
279
|
body: readStream,
|
|
206
280
|
contentLength: encResult.fileSize,
|
|
207
|
-
contentType: content
|
|
281
|
+
contentType: resolveMimetype(content)
|
|
208
282
|
});
|
|
209
283
|
const responseBody = await options.mediaTransfer.readResponseBytes(uploadResponse);
|
|
210
284
|
const parsed = parseUploadResponse(responseBody, uploadResponse.status);
|
|
@@ -213,7 +287,10 @@ async function uploadMediaStream(options, content, stream) {
|
|
|
213
287
|
mediaKey,
|
|
214
288
|
fileSha256: encResult.fileSha256,
|
|
215
289
|
fileEncSha256: encResult.fileEncSha256,
|
|
216
|
-
fileLength: encResult.plaintextLength
|
|
290
|
+
fileLength: encResult.plaintextLength,
|
|
291
|
+
streamingSidecar: encResult.streamingSidecar,
|
|
292
|
+
firstFrameSidecar: encResult.firstFrameSidecar,
|
|
293
|
+
firstFrameLength
|
|
217
294
|
};
|
|
218
295
|
}
|
|
219
296
|
finally {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Cryptographic utilities
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.aesCtrDecrypt = exports.aesCtrEncrypt = exports.pbkdf2DeriveAesCtrKey = exports.hmacSign = exports.importHmacSha512Key = exports.importHmacKey = exports.aesCbcDecrypt = exports.aesCbcEncrypt = exports.importAesCbcKey = exports.aesGcmDecrypt = exports.aesGcmEncrypt = exports.importAesGcmKey = exports.sha512 = exports.sha256 = exports.sha1 = exports.randomIntAsync = exports.randomFillAsync = exports.randomBytesAsync = exports.buildNonce = exports.readVersionedContent = exports.prependVersion = exports.toRawPubKey = exports.toSerializedPubKey = exports.hkdfSplit = exports.hkdf = exports.X25519 = exports.Ed25519 = void 0;
|
|
6
|
+
exports.xeddsaVerify = exports.xeddsaSign = exports.aesCtrDecrypt = exports.aesCtrEncrypt = exports.pbkdf2DeriveAesCtrKey = exports.hmacSign = exports.importHmacSha512Key = exports.importHmacKey = exports.aesCbcDecrypt = exports.aesCbcEncrypt = exports.importAesCbcKey = exports.aesGcmDecrypt = exports.aesGcmEncrypt = exports.importAesGcmKey = exports.sha512 = exports.sha256 = exports.sha1 = exports.randomIntAsync = exports.randomFillAsync = exports.randomBytesAsync = exports.buildNonce = exports.readVersionedContent = exports.prependVersion = exports.toRawPubKey = exports.toSerializedPubKey = exports.hkdfSplit = exports.hkdf = exports.X25519 = exports.Ed25519 = void 0;
|
|
7
7
|
var Ed25519_1 = require("../curves/Ed25519");
|
|
8
8
|
Object.defineProperty(exports, "Ed25519", { enumerable: true, get: function () { return Ed25519_1.Ed25519; } });
|
|
9
9
|
var X25519_1 = require("../curves/X25519");
|
|
@@ -38,3 +38,6 @@ Object.defineProperty(exports, "hmacSign", { enumerable: true, get: function ()
|
|
|
38
38
|
Object.defineProperty(exports, "pbkdf2DeriveAesCtrKey", { enumerable: true, get: function () { return primitives_1.pbkdf2DeriveAesCtrKey; } });
|
|
39
39
|
Object.defineProperty(exports, "aesCtrEncrypt", { enumerable: true, get: function () { return primitives_1.aesCtrEncrypt; } });
|
|
40
40
|
Object.defineProperty(exports, "aesCtrDecrypt", { enumerable: true, get: function () { return primitives_1.aesCtrDecrypt; } });
|
|
41
|
+
var xeddsa_1 = require("../core/xeddsa");
|
|
42
|
+
Object.defineProperty(exports, "xeddsaSign", { enumerable: true, get: function () { return xeddsa_1.xeddsaSign; } });
|
|
43
|
+
Object.defineProperty(exports, "xeddsaVerify", { enumerable: true, get: function () { return xeddsa_1.xeddsaVerify; } });
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.randomIntAsync = void 0;
|
|
4
|
-
exports.randomBytesAsync = randomBytesAsync;
|
|
3
|
+
exports.randomBytesAsync = exports.randomIntAsync = void 0;
|
|
5
4
|
exports.randomFillAsync = randomFillAsync;
|
|
6
5
|
const node_crypto_1 = require("node:crypto");
|
|
7
6
|
const node_util_1 = require("node:util");
|
|
8
|
-
const bytes_1 = require("../../util/bytes");
|
|
9
|
-
const randomBytesAsyncImpl = (0, node_util_1.promisify)(node_crypto_1.randomBytes);
|
|
10
|
-
const randomIntAsyncImpl = (0, node_util_1.promisify)(node_crypto_1.randomInt);
|
|
11
|
-
async function randomBytesAsync(size) {
|
|
12
|
-
return (0, bytes_1.toBytesView)(await randomBytesAsyncImpl(size));
|
|
13
|
-
}
|
|
14
7
|
async function randomFillAsync(target, offset, size) {
|
|
15
8
|
await new Promise((resolve, reject) => {
|
|
16
9
|
const onDone = (error) => {
|
|
@@ -32,4 +25,5 @@ async function randomFillAsync(target, offset, size) {
|
|
|
32
25
|
});
|
|
33
26
|
return target;
|
|
34
27
|
}
|
|
35
|
-
exports.randomIntAsync =
|
|
28
|
+
exports.randomIntAsync = (0, node_util_1.promisify)(node_crypto_1.randomInt);
|
|
29
|
+
exports.randomBytesAsync = (0, node_util_1.promisify)(node_crypto_1.randomBytes);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.xeddsaVerify = xeddsaVerify;
|
|
4
|
+
exports.xeddsaSign = xeddsaSign;
|
|
5
|
+
const primitives_1 = require("../core/primitives");
|
|
6
|
+
const random_1 = require("../core/random");
|
|
7
|
+
const Ed25519_1 = require("../curves/Ed25519");
|
|
8
|
+
const X25519_1 = require("../curves/X25519");
|
|
9
|
+
const edwards_1 = require("../math/edwards");
|
|
10
|
+
const le_1 = require("../math/le");
|
|
11
|
+
const mod_1 = require("../math/mod");
|
|
12
|
+
const bytes_1 = require("../../util/bytes");
|
|
13
|
+
const PREFIX_SIGNATURE_RANDOM = new Uint8Array([
|
|
14
|
+
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
15
|
+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
16
|
+
]);
|
|
17
|
+
async function xeddsaVerify(curvePublicKey, message, signature) {
|
|
18
|
+
if (signature.length !== 64) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if ((signature[63] & 0x60) !== 0) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const lastByteIndex = 63;
|
|
25
|
+
const originalLastByte = signature[lastByteIndex];
|
|
26
|
+
const signBit = originalLastByte & 0x80;
|
|
27
|
+
signature[lastByteIndex] = originalLastByte & 0x7f;
|
|
28
|
+
const edPublic = (0, X25519_1.montgomeryToEdwardsPublic)(curvePublicKey, signBit);
|
|
29
|
+
try {
|
|
30
|
+
return await Ed25519_1.Ed25519.verify(message, signature, edPublic);
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
signature[lastByteIndex] = originalLastByte;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function xeddsaSign(privateKey, message) {
|
|
37
|
+
(0, bytes_1.assertByteLength)(privateKey, 32, `invalid curve25519 private key length ${privateKey.length}`);
|
|
38
|
+
const clampedPrivateKey = (0, X25519_1.clampCurvePrivateKeyInPlace)(privateKey);
|
|
39
|
+
const privateScalar = (0, le_1.bytesToBigIntLE)(clampedPrivateKey);
|
|
40
|
+
const encodedPublic = (0, edwards_1.encodeExtendedPoint)((0, edwards_1.scalarMultBase)(privateScalar));
|
|
41
|
+
const pubKeySignBit = encodedPublic[31] & 0x80;
|
|
42
|
+
const randomSuffix = await (0, random_1.randomBytesAsync)(64);
|
|
43
|
+
const hashInput = (0, bytes_1.concatBytes)([
|
|
44
|
+
PREFIX_SIGNATURE_RANDOM,
|
|
45
|
+
clampedPrivateKey,
|
|
46
|
+
message,
|
|
47
|
+
randomSuffix
|
|
48
|
+
]);
|
|
49
|
+
const r = (0, mod_1.modGroup)((0, le_1.bytesToBigIntLE)(await (0, primitives_1.sha512)(hashInput)));
|
|
50
|
+
const encodedR = (0, edwards_1.encodeExtendedPoint)((0, edwards_1.scalarMultBase)(r));
|
|
51
|
+
const hInput = (0, bytes_1.concatBytes)([encodedR, encodedPublic, message]);
|
|
52
|
+
const h = (0, mod_1.modGroup)((0, le_1.bytesToBigIntLE)(await (0, primitives_1.sha512)(hInput)));
|
|
53
|
+
const s = (0, mod_1.modGroup)(r + h * privateScalar);
|
|
54
|
+
const encodedS = (0, le_1.bigIntToBytesLE)(s, 32);
|
|
55
|
+
encodedS[31] = (encodedS[31] & 0x7f) | pubKeySignBit;
|
|
56
|
+
return (0, bytes_1.concatBytes)([encodedR, encodedS]);
|
|
57
|
+
}
|
|
@@ -9,6 +9,8 @@ const types_1 = require("../curves/types");
|
|
|
9
9
|
const constants_2 = require("../math/constants");
|
|
10
10
|
const fe_1 = require("../math/fe");
|
|
11
11
|
const bytes_1 = require("../../util/bytes");
|
|
12
|
+
const runtime_1 = require("../../util/runtime");
|
|
13
|
+
const IS_BUN = (0, runtime_1.isBunRuntime)();
|
|
12
14
|
// Pre-allocated temps for montgomeryToEdwardsPublic (safe: single-threaded)
|
|
13
15
|
const _mx = (0, fe_1.fe)();
|
|
14
16
|
const _m1 = (0, fe_1.fe)();
|
|
@@ -69,6 +71,22 @@ class X25519 {
|
|
|
69
71
|
static async scalarMult(privKey, pubKey) {
|
|
70
72
|
(0, bytes_1.assertByteLength)(privKey, 32, 'x25519 private key must be 32 bytes');
|
|
71
73
|
(0, bytes_1.assertByteLength)(pubKey, 32, 'x25519 public key must be 32 bytes');
|
|
74
|
+
// TODO: When Bun supports deriveBits with X25519 change to Async Web Crypto API
|
|
75
|
+
// https://github.com/oven-sh/bun/pull/29152
|
|
76
|
+
if (IS_BUN) {
|
|
77
|
+
const spki = new Uint8Array(constants_1.X25519_SPKI_PREFIX.length + 32);
|
|
78
|
+
spki.set(constants_1.X25519_SPKI_PREFIX, 0);
|
|
79
|
+
spki.set(pubKey, constants_1.X25519_SPKI_PREFIX.length);
|
|
80
|
+
const shared = (0, node_crypto_1.diffieHellman)({
|
|
81
|
+
privateKey: (0, node_crypto_1.createPrivateKey)({
|
|
82
|
+
key: (0, types_1.pkcs8FromRawPrivate)(constants_1.X25519_PKCS8_PREFIX, privKey),
|
|
83
|
+
format: 'der',
|
|
84
|
+
type: 'pkcs8'
|
|
85
|
+
}),
|
|
86
|
+
publicKey: (0, node_crypto_1.createPublicKey)({ key: spki, format: 'der', type: 'spki' })
|
|
87
|
+
});
|
|
88
|
+
return (0, bytes_1.toBytesView)(shared);
|
|
89
|
+
}
|
|
72
90
|
const [privateKey, publicKey] = await Promise.all([
|
|
73
91
|
node_crypto_1.webcrypto.subtle.importKey('pkcs8', (0, types_1.pkcs8FromRawPrivate)(constants_1.X25519_PKCS8_PREFIX, privKey), { name: 'X25519' }, false, ['deriveBits']),
|
|
74
92
|
node_crypto_1.webcrypto.subtle.importKey('raw', pubKey, { name: 'X25519' }, false, [])
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ED25519_PKCS8_PREFIX = exports.X25519_PKCS8_PREFIX = void 0;
|
|
3
|
+
exports.ED25519_PKCS8_PREFIX = exports.X25519_SPKI_PREFIX = exports.X25519_PKCS8_PREFIX = void 0;
|
|
4
4
|
const bytes_1 = require("../../util/bytes");
|
|
5
5
|
exports.X25519_PKCS8_PREFIX = (0, bytes_1.hexToBytes)('302e020100300506032b656e04220420');
|
|
6
|
+
exports.X25519_SPKI_PREFIX = (0, bytes_1.hexToBytes)('302a300506032b656e032100');
|
|
6
7
|
exports.ED25519_PKCS8_PREFIX = (0, bytes_1.hexToBytes)('302e020100300506032b657004220420');
|
|
@@ -4,15 +4,18 @@ import { aesCbcDecrypt, aesCbcEncrypt, hmacSign, importAesCbcKey, importHmacKey,
|
|
|
4
4
|
import { randomBytesAsync } from '../crypto/core/random.js';
|
|
5
5
|
import { proto } from '../proto.js';
|
|
6
6
|
import { WA_APP_STATE_KDF_INFO } from '../protocol/constants.js';
|
|
7
|
-
import { bytesToBase64 } from '../util/bytes.js';
|
|
8
|
-
import { concatBytes, EMPTY_BYTES, intToBytes, TEXT_DECODER, TEXT_ENCODER, uint8Equal } from '../util/bytes.js';
|
|
7
|
+
import { bytesToBase64, concatBytes, EMPTY_BYTES, intToBytes, TEXT_DECODER, TEXT_ENCODER, uint8TimingSafeEqual } from '../util/bytes.js';
|
|
9
8
|
import { setBoundedMapEntry } from '../util/collections.js';
|
|
10
9
|
import { normalizeNonNegativeInteger } from '../util/primitives.js';
|
|
11
10
|
const DEFAULT_DERIVED_KEYS_CACHE_MAX_SIZE = 256;
|
|
12
11
|
export class WaAppStateCrypto {
|
|
13
|
-
constructor(derivedKeysCacheMaxSize = DEFAULT_DERIVED_KEYS_CACHE_MAX_SIZE) {
|
|
12
|
+
constructor(derivedKeysCacheMaxSize = DEFAULT_DERIVED_KEYS_CACHE_MAX_SIZE, skipMacVerification = false) {
|
|
14
13
|
this.derivedKeysCache = new Map();
|
|
15
14
|
this.derivedKeysCacheMaxSize = normalizeNonNegativeInteger(derivedKeysCacheMaxSize, DEFAULT_DERIVED_KEYS_CACHE_MAX_SIZE);
|
|
15
|
+
this.skipMacVerification = skipMacVerification;
|
|
16
|
+
}
|
|
17
|
+
get isMacVerificationSkipped() {
|
|
18
|
+
return this.skipMacVerification;
|
|
16
19
|
}
|
|
17
20
|
clearCache() {
|
|
18
21
|
this.derivedKeysCache.clear();
|
|
@@ -25,19 +28,25 @@ export class WaAppStateCrypto {
|
|
|
25
28
|
return cached;
|
|
26
29
|
}
|
|
27
30
|
const derived = await hkdf(keyData, null, WA_APP_STATE_KDF_INFO.MUTATION_KEYS, APP_STATE_DERIVED_KEY_LENGTH);
|
|
31
|
+
const [indexHmacKey, valueEncryptionAesKey, valueMacHmacKey, snapshotMacHmacKey, patchMacHmacKey] = await Promise.all([
|
|
32
|
+
importHmacKey(derived.subarray(0, APP_STATE_DERIVED_INDEX_KEY_END)),
|
|
33
|
+
importAesCbcKey(derived.subarray(APP_STATE_DERIVED_INDEX_KEY_END, APP_STATE_DERIVED_VALUE_ENCRYPTION_KEY_END)),
|
|
34
|
+
importHmacSha512Key(derived.subarray(APP_STATE_DERIVED_VALUE_ENCRYPTION_KEY_END, APP_STATE_DERIVED_VALUE_MAC_KEY_END)),
|
|
35
|
+
importHmacKey(derived.subarray(APP_STATE_DERIVED_VALUE_MAC_KEY_END, APP_STATE_DERIVED_SNAPSHOT_MAC_KEY_END)),
|
|
36
|
+
importHmacKey(derived.subarray(APP_STATE_DERIVED_SNAPSHOT_MAC_KEY_END, APP_STATE_DERIVED_PATCH_MAC_KEY_END))
|
|
37
|
+
]);
|
|
28
38
|
const keys = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
indexHmacKey,
|
|
40
|
+
valueEncryptionAesKey,
|
|
41
|
+
valueMacHmacKey,
|
|
42
|
+
snapshotMacHmacKey,
|
|
43
|
+
patchMacHmacKey
|
|
34
44
|
};
|
|
35
45
|
this.touchDerivedKeysCacheEntry(cacheKey, keys);
|
|
36
46
|
return keys;
|
|
37
47
|
}
|
|
38
|
-
async generateIndexMac(
|
|
39
|
-
|
|
40
|
-
return hmacSign(key, indexBytes);
|
|
48
|
+
async generateIndexMac(indexHmacKey, indexBytes) {
|
|
49
|
+
return hmacSign(indexHmacKey, indexBytes);
|
|
41
50
|
}
|
|
42
51
|
async encryptMutation(args) {
|
|
43
52
|
const derivedKeys = await this.deriveKeys(args.keyData);
|
|
@@ -52,13 +61,12 @@ export class WaAppStateCrypto {
|
|
|
52
61
|
if (iv.byteLength !== APP_STATE_IV_LENGTH) {
|
|
53
62
|
throw new Error(`invalid IV length ${iv.byteLength}`);
|
|
54
63
|
}
|
|
55
|
-
const indexMacPromise = this.generateIndexMac(derivedKeys.
|
|
56
|
-
const
|
|
57
|
-
const cipherText = await aesCbcEncrypt(encryptionKey, iv, encoded);
|
|
64
|
+
const indexMacPromise = this.generateIndexMac(derivedKeys.indexHmacKey, indexBytes);
|
|
65
|
+
const cipherText = await aesCbcEncrypt(derivedKeys.valueEncryptionAesKey, iv, encoded);
|
|
58
66
|
const cipherWithIv = concatBytes([iv, cipherText]);
|
|
59
67
|
const associatedData = this.generateAssociatedData(args.operation, args.keyId);
|
|
60
68
|
const [valueMac, indexMac] = await Promise.all([
|
|
61
|
-
this.generateValueMac(derivedKeys.
|
|
69
|
+
this.generateValueMac(derivedKeys.valueMacHmacKey, associatedData, cipherWithIv),
|
|
62
70
|
indexMacPromise
|
|
63
71
|
]);
|
|
64
72
|
return {
|
|
@@ -76,13 +84,14 @@ export class WaAppStateCrypto {
|
|
|
76
84
|
const mac = args.valueBlob.subarray(args.valueBlob.byteLength - APP_STATE_VALUE_MAC_LENGTH);
|
|
77
85
|
const cipherText = args.valueBlob.subarray(APP_STATE_IV_LENGTH, args.valueBlob.byteLength - APP_STATE_VALUE_MAC_LENGTH);
|
|
78
86
|
const cipherWithIv = args.valueBlob.subarray(0, args.valueBlob.byteLength - APP_STATE_VALUE_MAC_LENGTH);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
if (!this.skipMacVerification) {
|
|
88
|
+
const associatedData = this.generateAssociatedData(args.operation, args.keyId);
|
|
89
|
+
const expectedMac = await this.generateValueMac(derivedKeys.valueMacHmacKey, associatedData, cipherWithIv);
|
|
90
|
+
if (!uint8TimingSafeEqual(mac, expectedMac)) {
|
|
91
|
+
throw new Error('mutation value MAC mismatch');
|
|
92
|
+
}
|
|
83
93
|
}
|
|
84
|
-
const
|
|
85
|
-
const plaintext = await aesCbcDecrypt(decryptionKey, iv, cipherText);
|
|
94
|
+
const plaintext = await aesCbcDecrypt(derivedKeys.valueEncryptionAesKey, iv, cipherText);
|
|
86
95
|
const syncActionData = proto.SyncActionData.decode(plaintext);
|
|
87
96
|
if (!syncActionData.index) {
|
|
88
97
|
throw new Error('missing sync action index');
|
|
@@ -90,9 +99,11 @@ export class WaAppStateCrypto {
|
|
|
90
99
|
if (syncActionData.version === null || syncActionData.version === undefined) {
|
|
91
100
|
throw new Error('missing sync action version');
|
|
92
101
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
102
|
+
if (!this.skipMacVerification) {
|
|
103
|
+
const generatedIndexMac = await this.generateIndexMac(derivedKeys.indexHmacKey, syncActionData.index);
|
|
104
|
+
if (!uint8TimingSafeEqual(generatedIndexMac, args.indexMac)) {
|
|
105
|
+
throw new Error('mutation index MAC mismatch');
|
|
106
|
+
}
|
|
96
107
|
}
|
|
97
108
|
return {
|
|
98
109
|
index: TEXT_DECODER.decode(syncActionData.index),
|
|
@@ -109,8 +120,7 @@ export class WaAppStateCrypto {
|
|
|
109
120
|
intToBytes(8, version),
|
|
110
121
|
TEXT_ENCODER.encode(collectionName)
|
|
111
122
|
]);
|
|
112
|
-
|
|
113
|
-
return hmacSign(key, payload);
|
|
123
|
+
return hmacSign(derivedKeys.snapshotMacHmacKey, payload);
|
|
114
124
|
}
|
|
115
125
|
async generatePatchMac(keyData, snapshotMac, valueMacs, version, collectionName) {
|
|
116
126
|
const derivedKeys = await this.deriveKeys(keyData);
|
|
@@ -120,8 +130,7 @@ export class WaAppStateCrypto {
|
|
|
120
130
|
intToBytes(8, version),
|
|
121
131
|
TEXT_ENCODER.encode(collectionName)
|
|
122
132
|
]);
|
|
123
|
-
|
|
124
|
-
return hmacSign(key, payload);
|
|
133
|
+
return hmacSign(derivedKeys.patchMacHmacKey, payload);
|
|
125
134
|
}
|
|
126
135
|
async ltHashAdd(base, addValues) {
|
|
127
136
|
return this.ltHashApply(base, addValues, (left, right) => left + right);
|
|
@@ -175,11 +184,10 @@ export class WaAppStateCrypto {
|
|
|
175
184
|
out.set(keyId, 1);
|
|
176
185
|
return out;
|
|
177
186
|
}
|
|
178
|
-
async generateValueMac(
|
|
187
|
+
async generateValueMac(valueMacHmacKey, associatedData, cipherWithIv) {
|
|
179
188
|
const octetLength = new Uint8Array(APP_STATE_MAC_OCTET_LENGTH);
|
|
180
189
|
octetLength[octetLength.length - 1] = associatedData.byteLength & 0xff;
|
|
181
|
-
const
|
|
182
|
-
const full = await hmacSign(key, concatBytes([associatedData, cipherWithIv, octetLength]));
|
|
190
|
+
const full = await hmacSign(valueMacHmacKey, concatBytes([associatedData, cipherWithIv, octetLength]));
|
|
183
191
|
return full.subarray(0, APP_STATE_VALUE_MAC_LENGTH);
|
|
184
192
|
}
|
|
185
193
|
touchDerivedKeysCacheEntry(cacheKey, keys) {
|