@signalapp/libsignal-client 0.58.2 → 0.59.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/Native.d.ts CHANGED
@@ -143,6 +143,7 @@ type Serialized<T> = Buffer;
143
143
  export function registerErrors(errorsModule: Record<string, unknown>): void;
144
144
 
145
145
  export const enum LogLevel { Error = 1, Warn, Info, Debug, Trace }
146
+ export function AccountEntropyPool_Generate(): string;
146
147
  export function Aes256GcmSiv_Decrypt(aesGcmSiv: Wrapper<Aes256GcmSiv>, ctext: Buffer, nonce: Buffer, associatedData: Buffer): Buffer;
147
148
  export function Aes256GcmSiv_Encrypt(aesGcmSivObj: Wrapper<Aes256GcmSiv>, ptext: Buffer, nonce: Buffer, associatedData: Buffer): Buffer;
148
149
  export function Aes256GcmSiv_New(key: Buffer): Aes256GcmSiv;
@@ -507,6 +508,7 @@ export function TESTING_ChatServiceResponseConvert(bodyPresent: boolean): ChatRe
507
508
  export function TESTING_ChatService_InjectConnectionInterrupted(chat: Wrapper<AuthChat>): void;
508
509
  export function TESTING_ChatService_InjectIntentionalDisconnect(chat: Wrapper<AuthChat>): void;
509
510
  export function TESTING_ChatService_InjectRawServerRequest(chat: Wrapper<AuthChat>, bytes: Buffer): void;
511
+ export function TESTING_ConnectionManager_newLocalOverride(userAgent: string, chatPort: number, cdsiPort: number, svr2Port: number, svr3SgxPort: number, svr3NitroPort: number, svr3Tpm2SnpPort: number, rootCertificateDer: Buffer): ConnectionManager;
510
512
  export function TESTING_ErrorOnBorrowAsync(_input: null): Promise<void>;
511
513
  export function TESTING_ErrorOnBorrowIo(asyncRuntime: Wrapper<NonSuspendingBackgroundThreadRuntime>, _input: null): Promise<void>;
512
514
  export function TESTING_ErrorOnBorrowSync(_input: null): void;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The randomly-generated user-memorized entropy used to derive the backup key,
3
+ * with other possible future uses.
4
+ *
5
+ * Contains log_2(36^64) = ~330 bits of entropy.
6
+ */
7
+ export declare class AccountEntropyPool {
8
+ /**
9
+ * Randomly generates an Account Entropy Pool and returns the cannonical string
10
+ * representation of that pool.
11
+ *
12
+ * @returns cryptographically random 64 character string of characters a-z, 0-9
13
+ */
14
+ static generate(): string;
15
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2024 Signal Messenger, LLC.
4
+ // SPDX-License-Identifier: AGPL-3.0-only
5
+ //
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.AccountEntropyPool = void 0;
8
+ /**
9
+ * Cryptographic hashing, randomness generation, etc. related to SVR/Backup Keys.
10
+ *
11
+ * Currently only the Account Entropy Pool is exposed, because no other functionality is used on Desktop.
12
+ *
13
+ * @module AccountKeys
14
+ */
15
+ const Native = require("../Native");
16
+ /**
17
+ * The randomly-generated user-memorized entropy used to derive the backup key,
18
+ * with other possible future uses.
19
+ *
20
+ * Contains log_2(36^64) = ~330 bits of entropy.
21
+ */
22
+ class AccountEntropyPool {
23
+ /**
24
+ * Randomly generates an Account Entropy Pool and returns the cannonical string
25
+ * representation of that pool.
26
+ *
27
+ * @returns cryptographically random 64 character string of characters a-z, 0-9
28
+ */
29
+ static generate() {
30
+ return Native.AccountEntropyPool_Generate();
31
+ }
32
+ }
33
+ exports.AccountEntropyPool = AccountEntropyPool;
34
+ //# sourceMappingURL=AccountKeys.js.map
package/dist/Errors.d.ts CHANGED
@@ -46,6 +46,12 @@ export declare class LibSignalErrorBase extends Error {
46
46
  constructor(message: string, name: keyof typeof ErrorCode | undefined, operation: string, extraProps?: Record<string, unknown>);
47
47
  get addr(): ProtocolAddress | string;
48
48
  toString(): string;
49
+ is<E extends ErrorCode>(code: E): this is Extract<LibSignalError, {
50
+ code: E;
51
+ }>;
52
+ static is<E extends ErrorCode>(error: unknown, code: E): error is Extract<LibSignalError, {
53
+ code: E;
54
+ }>;
49
55
  }
50
56
  export type LibSignalErrorCommon = Omit<LibSignalErrorBase, 'addr'>;
51
57
  export type GenericError = LibSignalErrorCommon & {
@@ -165,4 +171,4 @@ export type BackupValidationError = LibSignalErrorCommon & {
165
171
  export type CancellationError = LibSignalErrorCommon & {
166
172
  code: ErrorCode.Cancelled;
167
173
  };
168
- export type LibSignalError = GenericError | DuplicatedMessageError | SealedSenderSelfSendError | UntrustedIdentityError | InvalidRegistrationIdError | VerificationFailedError | InvalidSessionError | InvalidSenderKeySessionError | NicknameCannotBeEmptyError | CannotStartWithDigitError | MissingSeparatorError | BadNicknameCharacterError | NicknameTooShortError | NicknameTooLongError | DiscriminatorCannotBeEmptyError | DiscriminatorCannotBeZeroError | DiscriminatorCannotBeSingleDigitError | DiscriminatorCannotHaveLeadingZerosError | BadDiscriminatorCharacterError | DiscriminatorTooLargeError | InputDataTooLong | InvalidEntropyDataLength | InvalidUsernameLinkEncryptedData | IoError | CdsiInvalidTokenError | InvalidUriError | InvalidMediaInputError | SvrDataMissingError | SvrRestoreFailedError | SvrRequestFailedError | UnsupportedMediaInputError | ChatServiceInactive | AppExpiredError | DeviceDelinkedError | CancellationError;
174
+ export type LibSignalError = GenericError | DuplicatedMessageError | SealedSenderSelfSendError | UntrustedIdentityError | InvalidRegistrationIdError | VerificationFailedError | InvalidSessionError | InvalidSenderKeySessionError | NicknameCannotBeEmptyError | CannotStartWithDigitError | MissingSeparatorError | BadNicknameCharacterError | NicknameTooShortError | NicknameTooLongError | DiscriminatorCannotBeEmptyError | DiscriminatorCannotBeZeroError | DiscriminatorCannotBeSingleDigitError | DiscriminatorCannotHaveLeadingZerosError | BadDiscriminatorCharacterError | DiscriminatorTooLargeError | InputDataTooLong | InvalidEntropyDataLength | InvalidUsernameLinkEncryptedData | IoError | CdsiInvalidTokenError | InvalidUriError | InvalidMediaInputError | SvrDataMissingError | SvrRestoreFailedError | SvrRequestFailedError | UnsupportedMediaInputError | ChatServiceInactive | AppExpiredError | DeviceDelinkedError | RateLimitedError | BackupValidationError | CancellationError;
package/dist/Errors.js CHANGED
@@ -81,6 +81,18 @@ class LibSignalErrorBase extends Error {
81
81
  toString() {
82
82
  return `${this.name} - ${this.operation}: ${this.message}`;
83
83
  }
84
+ /// Like `error.code === code`, but also providing access to any additional properties.
85
+ is(code) {
86
+ return this.code === code;
87
+ }
88
+ /// Like `error instanceof LibSignalErrorBase && error.code === code`, but all in one expression,
89
+ /// and providing access to any additional properties.
90
+ static is(error, code) {
91
+ if (error instanceof LibSignalErrorBase) {
92
+ return error.is(code);
93
+ }
94
+ return false;
95
+ }
84
96
  }
85
97
  exports.LibSignalErrorBase = LibSignalErrorBase;
86
98
  //# sourceMappingURL=Errors.js.map
@@ -669,7 +669,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see
669
669
 
670
670
  ```
671
671
 
672
- ## attest 0.1.0, libsignal-ffi 0.58.2, libsignal-jni 0.58.2, libsignal-jni-testing 0.58.2, libsignal-node 0.58.2, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-bridge-testing 0.1.0, libsignal-bridge-types 0.1.0, libsignal-core 0.1.0, signal-crypto 0.1.0, device-transfer 0.1.0, libsignal-keytrans 0.0.1, signal-media 0.1.0, libsignal-message-backup 0.1.0, libsignal-message-backup-macros 0.1.0, libsignal-net 0.1.0, libsignal-net-infra 0.1.0, signal-pin 0.1.0, poksho 0.7.0, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0
672
+ ## libsignal-account-keys 0.1.0, attest 0.1.0, libsignal-ffi 0.59.0, libsignal-jni 0.59.0, libsignal-jni-testing 0.59.0, libsignal-node 0.59.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-bridge-testing 0.1.0, libsignal-bridge-types 0.1.0, libsignal-core 0.1.0, signal-crypto 0.1.0, device-transfer 0.1.0, libsignal-keytrans 0.0.1, signal-media 0.1.0, libsignal-message-backup 0.1.0, libsignal-message-backup-macros 0.1.0, libsignal-net 0.1.0, libsignal-net-infra 0.1.0, poksho 0.7.0, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0
673
673
 
674
674
  ```
675
675
  GNU AFFERO GENERAL PUBLIC LICENSE
@@ -2,6 +2,7 @@
2
2
  /// <reference types="node" />
3
3
  import * as Native from '../Native';
4
4
  import * as stream from 'stream';
5
+ type CallbackType = (error?: Error | null) => void;
5
6
  export type ChunkSizeChoice = {
6
7
  kind: 'everyN';
7
8
  n: number;
@@ -11,20 +12,41 @@ export type ChunkSizeChoice = {
11
12
  };
12
13
  export declare function everyNthByte(n: number): ChunkSizeChoice;
13
14
  export declare function inferChunkSize(dataSize: number): ChunkSizeChoice;
15
+ /**
16
+ * @deprecated Use the DigestingPassThrough instead
17
+ */
14
18
  export declare class DigestingWritable extends stream.Writable {
15
19
  _nativeHandle: Native.IncrementalMac;
16
20
  _digests: Buffer[];
17
21
  constructor(key: Buffer, sizeChoice: ChunkSizeChoice);
18
22
  getFinalDigest(): Buffer;
19
- _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
20
- _final(callback: (error?: Error | null) => void): void;
23
+ _write(chunk: any, encoding: BufferEncoding, callback: CallbackType): void;
24
+ _final(callback: CallbackType): void;
21
25
  }
26
+ export declare class DigestingPassThrough extends stream.Transform {
27
+ private digester;
28
+ constructor(key: Buffer, sizeChoice: ChunkSizeChoice);
29
+ getFinalDigest(): Buffer;
30
+ _transform(data: Buffer, enc: BufferEncoding, callback: CallbackType): void;
31
+ _final(callback: CallbackType): void;
32
+ }
33
+ /**
34
+ * @deprecated Use the ValidatingPassThrough instead
35
+ */
22
36
  export declare class ValidatingWritable extends stream.Writable {
23
37
  _nativeHandle: Native.ValidatingMac;
24
38
  _validatedBytes: number;
25
39
  constructor(key: Buffer, sizeChoice: ChunkSizeChoice, digest: Buffer);
26
40
  validatedSize(): number;
27
- _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
28
- _final(callback: (error?: Error | null) => void): void;
41
+ _write(chunk: any, encoding: BufferEncoding, callback: CallbackType): void;
42
+ _final(callback: CallbackType): void;
43
+ }
44
+ export declare class ValidatingPassThrough extends stream.Transform {
45
+ private validator;
46
+ private buffer;
47
+ constructor(key: Buffer, sizeChoice: ChunkSizeChoice, digest: Buffer);
48
+ _transform(data: Buffer, enc: BufferEncoding, callback: CallbackType): void;
49
+ _final(callback: CallbackType): void;
29
50
  }
30
51
  export declare function chunkSizeInBytes(sizeChoice: ChunkSizeChoice): number;
52
+ export {};
@@ -4,7 +4,7 @@
4
4
  // SPDX-License-Identifier: AGPL-3.0-only
5
5
  //
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.chunkSizeInBytes = exports.ValidatingWritable = exports.DigestingWritable = exports.inferChunkSize = exports.everyNthByte = void 0;
7
+ exports.chunkSizeInBytes = exports.ValidatingPassThrough = exports.ValidatingWritable = exports.DigestingPassThrough = exports.DigestingWritable = exports.inferChunkSize = exports.everyNthByte = void 0;
8
8
  const Native = require("../Native");
9
9
  const stream = require("stream");
10
10
  const Errors_1 = require("./Errors");
@@ -16,6 +16,9 @@ function inferChunkSize(dataSize) {
16
16
  return { kind: 'chunksOf', dataSize: dataSize };
17
17
  }
18
18
  exports.inferChunkSize = inferChunkSize;
19
+ /**
20
+ * @deprecated Use the DigestingPassThrough instead
21
+ */
19
22
  class DigestingWritable extends stream.Writable {
20
23
  constructor(key, sizeChoice) {
21
24
  super();
@@ -42,6 +45,40 @@ class DigestingWritable extends stream.Writable {
42
45
  }
43
46
  }
44
47
  exports.DigestingWritable = DigestingWritable;
48
+ class DigestingPassThrough extends stream.Transform {
49
+ constructor(key, sizeChoice) {
50
+ super();
51
+ this.digester = new DigestingWritable(key, sizeChoice);
52
+ // We handle errors coming from write/end
53
+ this.digester.on('error', () => {
54
+ /* noop */
55
+ });
56
+ }
57
+ getFinalDigest() {
58
+ return this.digester.getFinalDigest();
59
+ }
60
+ _transform(data, enc, callback) {
61
+ this.digester.write(data, enc, (err) => {
62
+ if (err) {
63
+ return callback(err);
64
+ }
65
+ this.push(data);
66
+ callback();
67
+ });
68
+ }
69
+ _final(callback) {
70
+ this.digester.end((err) => {
71
+ if (err) {
72
+ return callback(err);
73
+ }
74
+ callback();
75
+ });
76
+ }
77
+ }
78
+ exports.DigestingPassThrough = DigestingPassThrough;
79
+ /**
80
+ * @deprecated Use the ValidatingPassThrough instead
81
+ */
45
82
  class ValidatingWritable extends stream.Writable {
46
83
  constructor(key, sizeChoice, digest) {
47
84
  super();
@@ -77,6 +114,68 @@ class ValidatingWritable extends stream.Writable {
77
114
  }
78
115
  }
79
116
  exports.ValidatingWritable = ValidatingWritable;
117
+ class ValidatingPassThrough extends stream.Transform {
118
+ constructor(key, sizeChoice, digest) {
119
+ super();
120
+ this.buffer = new Array();
121
+ this.validator = new ValidatingWritable(key, sizeChoice, digest);
122
+ // We handle errors coming from write/end
123
+ this.validator.on('error', () => {
124
+ /* noop */
125
+ });
126
+ }
127
+ _transform(data, enc, callback) {
128
+ const start = this.validator.validatedSize();
129
+ this.validator.write(data, enc, (err) => {
130
+ if (err) {
131
+ return callback(err);
132
+ }
133
+ this.buffer.push(data);
134
+ const end = this.validator.validatedSize();
135
+ const readySize = end - start;
136
+ // Fully buffer
137
+ if (readySize === 0) {
138
+ return callback(null);
139
+ }
140
+ const { buffer } = this;
141
+ this.buffer = [];
142
+ let validated = 0;
143
+ for (const chunk of buffer) {
144
+ validated += chunk.byteLength;
145
+ // Buffered chunk is fully validated - push it without slicing
146
+ if (validated <= readySize) {
147
+ this.push(chunk);
148
+ continue;
149
+ }
150
+ // Validation boundary lies within the chunk, split it
151
+ const notValidated = validated - readySize;
152
+ this.push(chunk.subarray(0, -notValidated));
153
+ this.buffer.push(chunk.subarray(-notValidated));
154
+ // Technically this chunk must be the last chunk so we could break,
155
+ // but for consistency keep looping.
156
+ }
157
+ callback(null);
158
+ });
159
+ }
160
+ _final(callback) {
161
+ const start = this.validator.validatedSize();
162
+ this.validator.end((err) => {
163
+ if (err) {
164
+ return callback(err);
165
+ }
166
+ const end = this.validator.validatedSize();
167
+ const readySize = end - start;
168
+ const buffer = Buffer.concat(this.buffer);
169
+ this.buffer = [];
170
+ if (buffer.byteLength !== readySize) {
171
+ return callback(new Error('Stream not fully processed'));
172
+ }
173
+ this.push(buffer);
174
+ callback(null);
175
+ });
176
+ }
177
+ }
178
+ exports.ValidatingPassThrough = ValidatingPassThrough;
80
179
  function chunkSizeInBytes(sizeChoice) {
81
180
  switch (sizeChoice.kind) {
82
181
  case 'everyN':
package/dist/net.d.ts CHANGED
@@ -169,6 +169,21 @@ export declare class UnauthenticatedChatService implements ChatService {
169
169
  }): Promise<Native.ChatResponse>;
170
170
  }
171
171
  export declare function buildHttpRequest(chatRequest: ChatRequest): Wrapper<Native.HttpRequest>;
172
+ export type NetConstructorOptions = Readonly<{
173
+ localTestServer?: false;
174
+ env: Environment;
175
+ userAgent: string;
176
+ } | {
177
+ localTestServer: true;
178
+ userAgent: string;
179
+ TESTING_localServer_chatPort: number;
180
+ TESTING_localServer_cdsiPort: number;
181
+ TESTING_localServer_svr2Port: number;
182
+ TESTING_localServer_svr3SgxPort: number;
183
+ TESTING_localServer_svr3NitroPort: number;
184
+ TESTING_localServer_svr3Tpm2SnpPort: number;
185
+ TESTING_localServer_rootCertificateDer: Buffer;
186
+ }>;
172
187
  export declare class Net {
173
188
  private readonly asyncContext;
174
189
  private readonly connectionManager;
@@ -176,7 +191,7 @@ export declare class Net {
176
191
  * Instance of the {@link Svr3Client} to access SVR3.
177
192
  */
178
193
  svr3: Svr3Client;
179
- constructor(env: Environment, userAgent: string);
194
+ constructor(options: NetConstructorOptions);
180
195
  /**
181
196
  * Creates a new instance of {@link AuthenticatedChatService}.
182
197
  *
package/dist/net.js CHANGED
@@ -141,9 +141,14 @@ function buildHttpRequest(chatRequest) {
141
141
  }
142
142
  exports.buildHttpRequest = buildHttpRequest;
143
143
  class Net {
144
- constructor(env, userAgent) {
144
+ constructor(options) {
145
145
  this.asyncContext = new TokioAsyncContext(Native.TokioAsyncContext_new());
146
- this.connectionManager = newNativeHandle(Native.ConnectionManager_new(env, userAgent));
146
+ if (options.localTestServer) {
147
+ this.connectionManager = newNativeHandle(Native.TESTING_ConnectionManager_newLocalOverride(options.userAgent, options.TESTING_localServer_chatPort, options.TESTING_localServer_cdsiPort, options.TESTING_localServer_svr2Port, options.TESTING_localServer_svr3SgxPort, options.TESTING_localServer_svr3NitroPort, options.TESTING_localServer_svr3Tpm2SnpPort, options.TESTING_localServer_rootCertificateDer));
148
+ }
149
+ else {
150
+ this.connectionManager = newNativeHandle(Native.ConnectionManager_new(options.env, options.userAgent));
151
+ }
147
152
  this.svr3 = new Svr3ClientImpl(this.asyncContext, this.connectionManager);
148
153
  }
149
154
  /**
package/dist/pin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export {
2
+ /** @deprecated AccountEntropyPool was moved to 'AccountKeys' */
3
+ AccountEntropyPool, } from './AccountKeys';
package/dist/pin.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2024 Signal Messenger, LLC.
4
+ // SPDX-License-Identifier: AGPL-3.0-only
5
+ //
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.AccountEntropyPool = void 0;
8
+ var AccountKeys_1 = require("./AccountKeys");
9
+ /** @deprecated AccountEntropyPool was moved to 'AccountKeys' */
10
+ Object.defineProperty(exports, "AccountEntropyPool", { enumerable: true, get: function () { return AccountKeys_1.AccountEntropyPool; } });
11
+ //# sourceMappingURL=pin.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalapp/libsignal-client",
3
- "version": "0.58.2",
3
+ "version": "0.59.0",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",