Move SignalProtocolStore off window

This commit is contained in:
Fedor Indutny
2025-10-06 17:02:13 -07:00
committed by GitHub
parent 065017ce52
commit 911133decd
36 changed files with 295 additions and 393 deletions
-1
View File
@@ -21,7 +21,6 @@ before(async () => {
window.testUtilities.prepareTests(); window.testUtilities.prepareTests();
delete window.testUtilities.prepareTests; delete window.testUtilities.prepareTests;
window.textsecure.storage.protocol = window.getSignalProtocolStore();
!(function () { !(function () {
class Reporter extends Mocha.reporters.HTML { class Reporter extends Mocha.reporters.HTML {
+7 -12
View File
@@ -42,6 +42,7 @@ import { validateConversation } from './util/validateConversation.js';
import { ConversationModel } from './models/conversations.js'; import { ConversationModel } from './models/conversations.js';
import { INITIAL_EXPIRE_TIMER_VERSION } from './util/expirationTimer.js'; import { INITIAL_EXPIRE_TIMER_VERSION } from './util/expirationTimer.js';
import { missingCaseError } from './util/missingCaseError.js'; import { missingCaseError } from './util/missingCaseError.js';
import { signalProtocolStore } from './SignalProtocolStore.js';
import type { import type {
ConversationAttributesType, ConversationAttributesType,
@@ -490,7 +491,7 @@ export class ConversationController {
version: 2, version: 2,
expireTimerVersion: INITIAL_EXPIRE_TIMER_VERSION, expireTimerVersion: INITIAL_EXPIRE_TIMER_VERSION,
unreadCount: 0, unreadCount: 0,
verified: window.textsecure.storage.protocol.VerifiedStatus.DEFAULT, verified: signalProtocolStore.VerifiedStatus.DEFAULT,
messageCount: 0, messageCount: 0,
sentMessageCount: 0, sentMessageCount: 0,
...additionalInitialProps, ...additionalInitialProps,
@@ -506,7 +507,7 @@ export class ConversationController {
version: 2, version: 2,
expireTimerVersion: INITIAL_EXPIRE_TIMER_VERSION, expireTimerVersion: INITIAL_EXPIRE_TIMER_VERSION,
unreadCount: 0, unreadCount: 0,
verified: window.textsecure.storage.protocol.VerifiedStatus.DEFAULT, verified: signalProtocolStore.VerifiedStatus.DEFAULT,
messageCount: 0, messageCount: 0,
sentMessageCount: 0, sentMessageCount: 0,
...additionalInitialProps, ...additionalInitialProps,
@@ -522,7 +523,7 @@ export class ConversationController {
version: 2, version: 2,
expireTimerVersion: INITIAL_EXPIRE_TIMER_VERSION, expireTimerVersion: INITIAL_EXPIRE_TIMER_VERSION,
unreadCount: 0, unreadCount: 0,
verified: window.textsecure.storage.protocol.VerifiedStatus.DEFAULT, verified: signalProtocolStore.VerifiedStatus.DEFAULT,
messageCount: 0, messageCount: 0,
sentMessageCount: 0, sentMessageCount: 0,
...additionalInitialProps, ...additionalInitialProps,
@@ -1366,17 +1367,13 @@ export class ConversationController {
log.warn(`${logId}: Delete all sessions tied to old conversationId`); log.warn(`${logId}: Delete all sessions tied to old conversationId`);
// Note: we use the conversationId here in case we've already lost our service id. // Note: we use the conversationId here in case we've already lost our service id.
await window.textsecure.storage.protocol.removeSessionsByConversation( await signalProtocolStore.removeSessionsByConversation(obsoleteId);
obsoleteId
);
log.warn( log.warn(
`${logId}: Delete all identity information tied to old conversationId` `${logId}: Delete all identity information tied to old conversationId`
); );
if (obsoleteServiceId) { if (obsoleteServiceId) {
await window.textsecure.storage.protocol.removeIdentityKey( await signalProtocolStore.removeIdentityKey(obsoleteServiceId);
obsoleteServiceId
);
} }
log.warn( log.warn(
@@ -1814,9 +1811,7 @@ export class ConversationController {
recipients.forEach(serviceId => { recipients.forEach(serviceId => {
drop( drop(
queue.add(async () => { queue.add(async () => {
await window.textsecure.storage.protocol.archiveAllSessions( await signalProtocolStore.archiveAllSessions(serviceId);
serviceId
);
}) })
); );
}); });
+28 -40
View File
@@ -30,6 +30,7 @@ import { Address } from './types/Address.js';
import { QualifiedAddress } from './types/QualifiedAddress.js'; import { QualifiedAddress } from './types/QualifiedAddress.js';
import type { ServiceIdString } from './types/ServiceId.js'; import type { ServiceIdString } from './types/ServiceId.js';
import { normalizeServiceId } from './types/ServiceId.js'; import { normalizeServiceId } from './types/ServiceId.js';
import { signalProtocolStore } from './SignalProtocolStore.js';
import type { Zone } from './util/Zone.js'; import type { Zone } from './util/Zone.js';
@@ -68,7 +69,7 @@ export class Sessions extends SessionStore {
address: ProtocolAddress, address: ProtocolAddress,
record: SessionRecord record: SessionRecord
): Promise<void> { ): Promise<void> {
await window.textsecure.storage.protocol.storeSession( await signalProtocolStore.storeSession(
toQualifiedAddress(this.#ourServiceId, address), toQualifiedAddress(this.#ourServiceId, address),
record, record,
{ zone: this.#zone } { zone: this.#zone }
@@ -77,10 +78,9 @@ export class Sessions extends SessionStore {
async getSession(name: ProtocolAddress): Promise<SessionRecord | null> { async getSession(name: ProtocolAddress): Promise<SessionRecord | null> {
const encodedAddress = toQualifiedAddress(this.#ourServiceId, name); const encodedAddress = toQualifiedAddress(this.#ourServiceId, name);
const record = await window.textsecure.storage.protocol.loadSession( const record = await signalProtocolStore.loadSession(encodedAddress, {
encodedAddress, zone: this.#zone,
{ zone: this.#zone } });
);
return record || null; return record || null;
} }
@@ -91,7 +91,7 @@ export class Sessions extends SessionStore {
const encodedAddresses = addresses.map(addr => const encodedAddresses = addresses.map(addr =>
toQualifiedAddress(this.#ourServiceId, addr) toQualifiedAddress(this.#ourServiceId, addr)
); );
return window.textsecure.storage.protocol.loadSessions(encodedAddresses, { return signalProtocolStore.loadSessions(encodedAddresses, {
zone: this.#zone, zone: this.#zone,
}); });
} }
@@ -114,9 +114,7 @@ export class IdentityKeys extends IdentityKeyStore {
} }
async getIdentityKey(): Promise<PrivateKey> { async getIdentityKey(): Promise<PrivateKey> {
const keyPair = window.textsecure.storage.protocol.getIdentityKeyPair( const keyPair = signalProtocolStore.getIdentityKeyPair(this.#ourServiceId);
this.#ourServiceId
);
if (!keyPair) { if (!keyPair) {
throw new Error('IdentityKeyStore/getIdentityKey: No identity key!'); throw new Error('IdentityKeyStore/getIdentityKey: No identity key!');
} }
@@ -124,7 +122,7 @@ export class IdentityKeys extends IdentityKeyStore {
} }
async getLocalRegistrationId(): Promise<number> { async getLocalRegistrationId(): Promise<number> {
const id = await window.textsecure.storage.protocol.getLocalRegistrationId( const id = await signalProtocolStore.getLocalRegistrationId(
this.#ourServiceId this.#ourServiceId
); );
if (!isNumber(id)) { if (!isNumber(id)) {
@@ -137,7 +135,7 @@ export class IdentityKeys extends IdentityKeyStore {
async getIdentity(address: ProtocolAddress): Promise<PublicKey | null> { async getIdentity(address: ProtocolAddress): Promise<PublicKey | null> {
const encodedAddress = encodeAddress(address); const encodedAddress = encodeAddress(address);
const key = await window.textsecure.storage.protocol.loadIdentityKey( const key = await signalProtocolStore.loadIdentityKey(
encodedAddress.serviceId encodedAddress.serviceId
); );
@@ -157,12 +155,9 @@ export class IdentityKeys extends IdentityKeyStore {
// Pass `zone` to let `saveIdentity` archive sibling sessions when identity // Pass `zone` to let `saveIdentity` archive sibling sessions when identity
// key changes. // key changes.
return window.textsecure.storage.protocol.saveIdentity( return signalProtocolStore.saveIdentity(encodedAddress, publicKey, false, {
encodedAddress, zone: this.#zone,
publicKey, });
false,
{ zone: this.#zone }
);
} }
async isTrustedIdentity( async isTrustedIdentity(
@@ -173,7 +168,7 @@ export class IdentityKeys extends IdentityKeyStore {
const encodedAddress = encodeAddress(name); const encodedAddress = encodeAddress(name);
const publicKey = key.serialize(); const publicKey = key.serialize();
return window.textsecure.storage.protocol.isTrustedIdentity( return signalProtocolStore.isTrustedIdentity(
encodedAddress, encodedAddress,
publicKey, publicKey,
direction direction
@@ -201,10 +196,7 @@ export class PreKeys extends PreKeyStore {
} }
async getPreKey(id: number): Promise<PreKeyRecord> { async getPreKey(id: number): Promise<PreKeyRecord> {
const preKey = await window.textsecure.storage.protocol.loadPreKey( const preKey = await signalProtocolStore.loadPreKey(this.#ourServiceId, id);
this.#ourServiceId,
id
);
if (preKey === undefined) { if (preKey === undefined) {
throw new Error(`getPreKey: PreKey ${id} not found`); throw new Error(`getPreKey: PreKey ${id} not found`);
@@ -214,11 +206,9 @@ export class PreKeys extends PreKeyStore {
} }
async removePreKey(id: number): Promise<void> { async removePreKey(id: number): Promise<void> {
await window.textsecure.storage.protocol.removePreKeys( await signalProtocolStore.removePreKeys(this.#ourServiceId, [id], {
this.#ourServiceId, zone: this.#zone,
[id], });
{ zone: this.#zone }
);
} }
} }
@@ -237,11 +227,10 @@ export class KyberPreKeys extends KyberPreKeyStore {
} }
async getKyberPreKey(id: number): Promise<KyberPreKeyRecord> { async getKyberPreKey(id: number): Promise<KyberPreKeyRecord> {
const kyberPreKey = const kyberPreKey = await signalProtocolStore.loadKyberPreKey(
await window.textsecure.storage.protocol.loadKyberPreKey( this.#ourServiceId,
this.#ourServiceId, id
id );
);
if (kyberPreKey === undefined) { if (kyberPreKey === undefined) {
throw new Error(`getKyberPreKey: KyberPreKey ${id} not found`); throw new Error(`getKyberPreKey: KyberPreKey ${id} not found`);
@@ -255,7 +244,7 @@ export class KyberPreKeys extends KyberPreKeyStore {
signedPreKeyId: number, signedPreKeyId: number,
baseKey: PublicKey baseKey: PublicKey
): Promise<void> { ): Promise<void> {
await window.textsecure.storage.protocol.maybeRemoveKyberPreKey( await signalProtocolStore.maybeRemoveKyberPreKey(
this.#ourServiceId, this.#ourServiceId,
{ keyId, signedPreKeyId, baseKey }, { keyId, signedPreKeyId, baseKey },
{ zone: this.#zone } { zone: this.#zone }
@@ -285,7 +274,7 @@ export class SenderKeys extends SenderKeyStore {
): Promise<void> { ): Promise<void> {
const encodedAddress = toQualifiedAddress(this.#ourServiceId, sender); const encodedAddress = toQualifiedAddress(this.#ourServiceId, sender);
await window.textsecure.storage.protocol.saveSenderKey( await signalProtocolStore.saveSenderKey(
encodedAddress, encodedAddress,
distributionId, distributionId,
record, record,
@@ -299,7 +288,7 @@ export class SenderKeys extends SenderKeyStore {
): Promise<SenderKeyRecord | null> { ): Promise<SenderKeyRecord | null> {
const encodedAddress = toQualifiedAddress(this.#ourServiceId, sender); const encodedAddress = toQualifiedAddress(this.#ourServiceId, sender);
const senderKey = await window.textsecure.storage.protocol.getSenderKey( const senderKey = await signalProtocolStore.getSenderKey(
encodedAddress, encodedAddress,
distributionId, distributionId,
{ zone: this.zone } { zone: this.zone }
@@ -327,11 +316,10 @@ export class SignedPreKeys extends SignedPreKeyStore {
} }
async getSignedPreKey(id: number): Promise<SignedPreKeyRecord> { async getSignedPreKey(id: number): Promise<SignedPreKeyRecord> {
const signedPreKey = const signedPreKey = await signalProtocolStore.loadSignedPreKey(
await window.textsecure.storage.protocol.loadSignedPreKey( this.#ourServiceId,
this.#ourServiceId, id
id );
);
if (!signedPreKey) { if (!signedPreKey) {
throw new Error(`getSignedPreKey: SignedPreKey ${id} not found`); throw new Error(`getSignedPreKey: SignedPreKey ${id} not found`);
+1 -5
View File
@@ -2838,8 +2838,4 @@ export class SignalProtocolStore extends EventEmitter {
} }
} }
export function getSignalProtocolStore(): SignalProtocolStore { export const signalProtocolStore = new SignalProtocolStore();
return new SignalProtocolStore();
}
window.SignalProtocolStore = SignalProtocolStore;
+27 -8
View File
@@ -9,6 +9,7 @@ import { v7 as generateUuid } from 'uuid';
import * as Registration from './util/registration.js'; import * as Registration from './util/registration.js';
import MessageReceiver from './textsecure/MessageReceiver.js'; import MessageReceiver from './textsecure/MessageReceiver.js';
import { signalProtocolStore } from './SignalProtocolStore.js';
import type { import type {
SessionResetsType, SessionResetsType,
ProcessedDataMessage, ProcessedDataMessage,
@@ -269,8 +270,6 @@ export async function cleanupSessionResets(): Promise<void> {
} }
export async function startApp(): Promise<void> { export async function startApp(): Promise<void> {
window.textsecure.storage.protocol = new window.SignalProtocolStore();
if (window.initialTheme === ThemeType.light) { if (window.initialTheme === ThemeType.light) {
document.body.classList.add('light-theme'); document.body.classList.add('light-theme');
} }
@@ -390,8 +389,8 @@ export async function startApp(): Promise<void> {
window.SignalContext.getResolvedMessagesLocaleDirection() window.SignalContext.getResolvedMessagesLocaleDirection()
); );
KeyChangeListener.init(window.textsecure.storage.protocol); KeyChangeListener.init(signalProtocolStore);
window.textsecure.storage.protocol.on( signalProtocolStore.on(
'lowKeys', 'lowKeys',
throttle( throttle(
async () => { async () => {
@@ -403,7 +402,7 @@ export async function startApp(): Promise<void> {
) )
); );
window.textsecure.storage.protocol.on('removeAllData', () => { signalProtocolStore.on('removeAllData', () => {
window.reduxActions.stories.removeAllStories(); window.reduxActions.stories.removeAllStories();
}); });
@@ -525,7 +524,27 @@ export async function startApp(): Promise<void> {
const buildExpirationService = new BuildExpirationService(); const buildExpirationService = new BuildExpirationService();
server = window.WebAPI.connect({ const { config } = window.SignalContext;
const WebAPI = window.textsecure.WebAPI.initialize({
chatServiceUrl: config.serverUrl,
storageUrl: config.storageUrl,
updatesUrl: config.updatesUrl,
resourcesUrl: config.resourcesUrl,
cdnUrlObject: {
0: config.cdnUrl0,
2: config.cdnUrl2,
3: config.cdnUrl3,
},
certificateAuthority: config.certificateAuthority,
contentProxyUrl: config.contentProxyUrl,
proxyUrl: config.proxyUrl,
version: config.version,
disableIPv6: config.disableIPv6,
stripePublishableKey: config.stripePublishableKey,
});
server = WebAPI.connect({
...window.textsecure.storage.user.getWebAPICredentials(), ...window.textsecure.storage.user.getWebAPICredentials(),
hasBuildExpired: buildExpirationService.hasBuildExpired(), hasBuildExpired: buildExpirationService.hasBuildExpired(),
hasStoriesDisabled: window.storage.get('hasStoriesDisabled', false), hasStoriesDisabled: window.storage.get('hasStoriesDisabled', false),
@@ -1181,7 +1200,7 @@ export async function startApp(): Promise<void> {
await Promise.all([ await Promise.all([
window.ConversationController.getOrCreateSignalConversation(), window.ConversationController.getOrCreateSignalConversation(),
window.textsecure.storage.protocol.hydrateCaches(), signalProtocolStore.hydrateCaches(),
loadAll(), loadAll(),
]); ]);
await window.ConversationController.checkForConflicts(); await window.ConversationController.checkForConflicts();
@@ -3292,7 +3311,7 @@ export async function startApp(): Promise<void> {
await DataReader.getItemById('manifestVersion'); await DataReader.getItemById('manifestVersion');
// Finally, conversations in the database, and delete all config tables // Finally, conversations in the database, and delete all config tables
await window.textsecure.storage.protocol.removeAllConfiguration(); await signalProtocolStore.removeAllConfiguration();
// These three bits of data are important to ensure that the app loads up // These three bits of data are important to ensure that the app loads up
// the conversation list, instead of showing just the QR code screen. // the conversation list, instead of showing just the QR code screen.
+1 -1
View File
@@ -8,7 +8,7 @@ import type { DraftBodyRanges, RawBodyRange } from './types/BodyRange.js';
import type { CustomColorType, ConversationColorType } from './types/Colors.js'; import type { CustomColorType, ConversationColorType } from './types/Colors.js';
import type { SendMessageChallengeData } from './textsecure/Errors.js'; import type { SendMessageChallengeData } from './textsecure/Errors.js';
import type { ProfileNameChangeType } from './util/getStringForProfileChange.js'; import type { ProfileNameChangeType } from './util/getStringForProfileChange.js';
import type { CapabilitiesType } from './textsecure/WebAPI.js'; import type { CapabilitiesType } from './types/Capabilities.d.ts';
import type { ReadStatus } from './messages/MessageReadStatus.js'; import type { ReadStatus } from './messages/MessageReadStatus.js';
import type { SendStateByConversationId } from './messages/MessageSendState.js'; import type { SendStateByConversationId } from './messages/MessageSendState.js';
import type { GroupNameCollisionsWithIdsByTitle } from './util/groupMemberNameCollisions.js'; import type { GroupNameCollisionsWithIdsByTitle } from './util/groupMemberNameCollisions.js';
+17 -21
View File
@@ -97,6 +97,7 @@ import * as Bytes from '../Bytes.js';
import type { DraftBodyRanges } from '../types/BodyRange.js'; import type { DraftBodyRanges } from '../types/BodyRange.js';
import { migrateColor } from '../util/migrateColor.js'; import { migrateColor } from '../util/migrateColor.js';
import { isNotNil } from '../util/isNotNil.js'; import { isNotNil } from '../util/isNotNil.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
import { shouldSaveNotificationAvatarToDisk } from '../services/notifications.js'; import { shouldSaveNotificationAvatarToDisk } from '../services/notifications.js';
import { storageServiceUploadJob } from '../services/storage.js'; import { storageServiceUploadJob } from '../services/storage.js';
import { getSendOptions } from '../util/getSendOptions.js'; import { getSendOptions } from '../util/getSendOptions.js';
@@ -321,7 +322,7 @@ export class ConversationModel {
#lastIsTyping?: boolean; #lastIsTyping?: boolean;
#muteTimer?: NodeJS.Timeout; #muteTimer?: NodeJS.Timeout;
#privVerifiedEnum?: typeof window.textsecure.storage.protocol.VerifiedStatus; #privVerifiedEnum?: typeof signalProtocolStore.VerifiedStatus;
#isShuttingDown = false; #isShuttingDown = false;
#savePromises = new Set<Promise<void>>(); #savePromises = new Set<Promise<void>>();
@@ -418,7 +419,7 @@ export class ConversationModel {
this.storeName = 'conversations'; this.storeName = 'conversations';
this.#privVerifiedEnum = window.textsecure.storage.protocol.VerifiedStatus; this.#privVerifiedEnum = signalProtocolStore.VerifiedStatus;
// This may be overridden by window.ConversationController.getOrCreate, and signify // This may be overridden by window.ConversationController.getOrCreate, and signify
// our first save to the database. Or first fetch from the database. // our first save to the database. Or first fetch from the database.
@@ -522,7 +523,7 @@ export class ConversationModel {
}; };
} }
get #verifiedEnum(): typeof window.textsecure.storage.protocol.VerifiedStatus { get #verifiedEnum(): typeof signalProtocolStore.VerifiedStatus {
strictAssert(this.#privVerifiedEnum, 'ConversationModel not initialize'); strictAssert(this.#privVerifiedEnum, 'ConversationModel not initialize');
return this.#privVerifiedEnum; return this.#privVerifiedEnum;
} }
@@ -2116,7 +2117,7 @@ export class ConversationModel {
// for the case where we need to do old and new PNI comparisons. We'll wait // for the case where we need to do old and new PNI comparisons. We'll wait
// for the PNI update to do that. // for the PNI update to do that.
if (oldValue && oldValue !== this.getPni()) { if (oldValue && oldValue !== this.getPni()) {
drop(window.textsecure.storage.protocol.removeIdentityKey(oldValue)); drop(signalProtocolStore.removeIdentityKey(oldValue));
} }
this.captureChange('updateServiceId'); this.captureChange('updateServiceId');
@@ -2176,9 +2177,8 @@ export class ConversationModel {
// We're going from an old PNI to a new PNI // We're going from an old PNI to a new PNI
if (pni) { if (pni) {
const oldIdentityRecord = const oldIdentityRecord =
window.textsecure.storage.protocol.getIdentityRecord(oldValue); signalProtocolStore.getIdentityRecord(oldValue);
const newIdentityRecord = const newIdentityRecord = signalProtocolStore.getIdentityRecord(pni);
window.textsecure.storage.protocol.getIdentityRecord(pni);
if ( if (
newIdentityRecord && newIdentityRecord &&
@@ -2197,7 +2197,7 @@ export class ConversationModel {
// We're just dropping the PNI // We're just dropping the PNI
if (!pni) { if (!pni) {
const oldIdentityRecord = const oldIdentityRecord =
window.textsecure.storage.protocol.getIdentityRecord(oldValue); signalProtocolStore.getIdentityRecord(oldValue);
if (oldIdentityRecord) { if (oldIdentityRecord) {
this.trackPreviousIdentityKey(oldIdentityRecord.publicKey); this.trackPreviousIdentityKey(oldIdentityRecord.publicKey);
@@ -2207,7 +2207,7 @@ export class ConversationModel {
// If this PNI is going away or going to someone else, we'll delete all its sessions // If this PNI is going away or going to someone else, we'll delete all its sessions
if (oldValue) { if (oldValue) {
drop(window.textsecure.storage.protocol.removeIdentityKey(oldValue)); drop(signalProtocolStore.removeIdentityKey(oldValue));
} }
if (pni && !this.getServiceId()) { if (pni && !this.getServiceId()) {
@@ -2877,7 +2877,7 @@ export class ConversationModel {
} }
try { try {
return await window.textsecure.storage.protocol.getVerified(serviceId); return await signalProtocolStore.getVerified(serviceId);
} catch { } catch {
return this.#verifiedEnum.DEFAULT; return this.#verifiedEnum.DEFAULT;
} }
@@ -2942,9 +2942,9 @@ export class ConversationModel {
const keyChange = false; const keyChange = false;
if (aci) { if (aci) {
if (verified === this.#verifiedEnum.DEFAULT) { if (verified === this.#verifiedEnum.DEFAULT) {
await window.textsecure.storage.protocol.setVerified(aci, verified); await signalProtocolStore.setVerified(aci, verified);
} else { } else {
await window.textsecure.storage.protocol.setVerified(aci, verified, { await signalProtocolStore.setVerified(aci, verified, {
firstUse: false, firstUse: false,
nonblockingApproval: true, nonblockingApproval: true,
}); });
@@ -2997,7 +2997,7 @@ export class ConversationModel {
return; return;
} }
const key = await window.textsecure.storage.protocol.loadIdentityKey(aci); const key = await signalProtocolStore.loadIdentityKey(aci);
if (!key) { if (!key) {
throw new Error( throw new Error(
`sendVerifySyncMessage: No identity key found for aci ${aci}` `sendVerifySyncMessage: No identity key found for aci ${aci}`
@@ -3089,7 +3089,7 @@ export class ConversationModel {
} }
return this.queueJob('setApproved', async () => { return this.queueJob('setApproved', async () => {
return window.textsecure.storage.protocol.setApproval(serviceId, true); return signalProtocolStore.setApproval(serviceId, true);
}); });
} }
@@ -3097,10 +3097,7 @@ export class ConversationModel {
try { try {
const serviceId = this.getServiceId(); const serviceId = this.getServiceId();
strictAssert(serviceId, `No serviceId for conversation: ${this.id}`); strictAssert(serviceId, `No serviceId for conversation: ${this.id}`);
return window.textsecure.storage.protocol.isUntrusted( return signalProtocolStore.isUntrusted(serviceId, timestampThreshold);
serviceId,
timestampThreshold
);
} catch (err) { } catch (err) {
return false; return false;
} }
@@ -3357,8 +3354,7 @@ export class ConversationModel {
return; return;
} }
const hadSession = const hadSession = await signalProtocolStore.hasSessionWith(originalPni);
await window.textsecure.storage.protocol.hasSessionWith(originalPni);
if (!hadSession) { if (!hadSession) {
log.info(`${logId}: not adding, no PNI session`); log.info(`${logId}: not adding, no PNI session`);
@@ -5776,7 +5772,7 @@ export class ConversationModel {
if (!this.get('shareMyPhoneNumber')) { if (!this.get('shareMyPhoneNumber')) {
return undefined; return undefined;
} }
return window.textsecure.storage.protocol.signAlternateIdentity(); return signalProtocolStore.signAlternateIdentity();
} }
/** @return only undefined if not a group */ /** @return only undefined if not a group */
+2 -1
View File
@@ -86,6 +86,7 @@ import { SendStatus } from '../../messages/MessageSendState.js';
import type { SendStateByConversationId } from '../../messages/MessageSendState.js'; import type { SendStateByConversationId } from '../../messages/MessageSendState.js';
import { SeenStatus } from '../../MessageSeenStatus.js'; import { SeenStatus } from '../../MessageSeenStatus.js';
import { constantTimeEqual, deriveAccessKey } from '../../Crypto.js'; import { constantTimeEqual, deriveAccessKey } from '../../Crypto.js';
import { signalProtocolStore } from '../../SignalProtocolStore.js';
import * as Bytes from '../../Bytes.js'; import * as Bytes from '../../Bytes.js';
import { BACKUP_VERSION, WALLPAPER_TO_BUBBLE_COLOR } from './constants.js'; import { BACKUP_VERSION, WALLPAPER_TO_BUBBLE_COLOR } from './constants.js';
import { UnsupportedBackupVersion } from './errors.js'; import { UnsupportedBackupVersion } from './errors.js';
@@ -386,7 +387,7 @@ export class BackupImportStream extends Writable {
await window.storage.fetch(); await window.storage.fetch();
// Load identity keys we just saved. // Load identity keys we just saved.
await window.storage.protocol.hydrateCaches(); await signalProtocolStore.hydrateCaches();
// Load all data into redux (need to do this before updating a // Load all data into redux (need to do this before updating a
// conversation's last message, which uses redux selectors) // conversation's last message, which uses redux selectors)
+2 -1
View File
@@ -45,6 +45,7 @@ import {
import { HTTPError } from '../../types/HTTPError.js'; import { HTTPError } from '../../types/HTTPError.js';
import { constantTimeEqual } from '../../Crypto.js'; import { constantTimeEqual } from '../../Crypto.js';
import { measureSize } from '../../AttachmentCrypto.js'; import { measureSize } from '../../AttachmentCrypto.js';
import { signalProtocolStore } from '../../SignalProtocolStore.js';
import { isTestOrMockEnvironment } from '../../environment.js'; import { isTestOrMockEnvironment } from '../../environment.js';
import { runStorageServiceSyncJob } from '../storage.js'; import { runStorageServiceSyncJob } from '../storage.js';
import { BackupExportStream, type StatsType } from './export.js'; import { BackupExportStream, type StatsType } from './export.js';
@@ -1014,7 +1015,7 @@ export class BackupsService {
try { try {
log.info('backups.unlinkAndDeleteAllData: deleting all data'); log.info('backups.unlinkAndDeleteAllData: deleting all data');
await window.textsecure.storage.protocol.removeAllData(); await signalProtocolStore.removeAllData();
log.info('backups.unlinkAndDeleteAllData: all data deleted successfully'); log.info('backups.unlinkAndDeleteAllData: all data deleted successfully');
} catch (e) { } catch (e) {
log.error( log.error(
+5 -6
View File
@@ -165,6 +165,7 @@ import { createIdenticon } from '../util/createIdenticon.js';
import { getColorForCallLink } from '../util/getColorForCallLink.js'; import { getColorForCallLink } from '../util/getColorForCallLink.js';
import OS from '../util/os/osMain.js'; import OS from '../util/os/osMain.js';
import { sleep } from '../util/sleep.js'; import { sleep } from '../util/sleep.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
const { uniqBy, noop, compact } = lodash; const { uniqBy, noop, compact } = lodash;
@@ -2885,7 +2886,7 @@ export class CallingClass {
const { storage } = window.textsecure; const { storage } = window.textsecure;
const senderIdentityRecord = const senderIdentityRecord =
await storage.protocol.getOrMigrateIdentityRecord(remoteUserId); await signalProtocolStore.getOrMigrateIdentityRecord(remoteUserId);
if (!senderIdentityRecord) { if (!senderIdentityRecord) {
log.error( log.error(
`${logId}: Missing sender identity record; ignoring call message.` `${logId}: Missing sender identity record; ignoring call message.`
@@ -2896,7 +2897,8 @@ export class CallingClass {
const ourAci = storage.user.getCheckedAci(); const ourAci = storage.user.getCheckedAci();
const receiverIdentityRecord = storage.protocol.getIdentityRecord(ourAci); const receiverIdentityRecord =
signalProtocolStore.getIdentityRecord(ourAci);
if (!receiverIdentityRecord) { if (!receiverIdentityRecord) {
log.error( log.error(
`${logId}: Missing receiver identity record; ignoring call message.` `${logId}: Missing receiver identity record; ignoring call message.`
@@ -3324,10 +3326,7 @@ export class CallingClass {
// This is mostly the safety number check, unverified meaning that they were // This is mostly the safety number check, unverified meaning that they were
// verified before but now they are not. // verified before but now they are not.
const verifiedEnum = await conversation.safeGetVerified(); const verifiedEnum = await conversation.safeGetVerified();
if ( if (verifiedEnum === signalProtocolStore.VerifiedStatus.UNVERIFIED) {
verifiedEnum ===
window.textsecure.storage.protocol.VerifiedStatus.UNVERIFIED
) {
log.info(`${logId}: Peer is not trusted, ignoring incoming call`); log.info(`${logId}: Peer is not trusted, ignoring incoming call`);
const localCallEvent = LocalCallEvent.Missed; const localCallEvent = LocalCallEvent.Missed;
+5 -3
View File
@@ -10,7 +10,8 @@ import { IdentityChange } from '@signalapp/libsignal-client';
import type { ReadonlyDeep } from 'type-fest'; import type { ReadonlyDeep } from 'type-fest';
import type { ConversationModel } from '../models/conversations.js'; import type { ConversationModel } from '../models/conversations.js';
import type { CapabilitiesType, ProfileType } from '../textsecure/WebAPI.js'; import type { CapabilitiesType } from '../types/Capabilities.d.ts';
import type { ProfileType } from '../textsecure/WebAPI.js';
import MessageSender from '../textsecure/SendMessage.js'; import MessageSender from '../textsecure/SendMessage.js';
import type { ServiceIdString } from '../types/ServiceId.js'; import type { ServiceIdString } from '../types/ServiceId.js';
import { DataWriter } from '../sql/Client.js'; import { DataWriter } from '../sql/Client.js';
@@ -44,6 +45,7 @@ import {
onFailedToSendWithEndorsements, onFailedToSendWithEndorsements,
} from '../util/groupSendEndorsements.js'; } from '../util/groupSendEndorsements.js';
import { ProfileDecryptError } from '../types/errors.js'; import { ProfileDecryptError } from '../types/errors.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
const log = createLogger('profiles'); const log = createLogger('profiles');
@@ -852,7 +854,7 @@ export async function updateIdentityKey(
return false; return false;
} }
const saveOutcome = await window.textsecure.storage.protocol.saveIdentity( const saveOutcome = await signalProtocolStore.saveIdentity(
new Address(serviceId, 1), new Address(serviceId, 1),
identityKey, identityKey,
false, false,
@@ -864,7 +866,7 @@ export async function updateIdentityKey(
// save identity will close all sessions except for .1, so we // save identity will close all sessions except for .1, so we
// must close that one manually. // must close that one manually.
const ourAci = window.textsecure.storage.user.getCheckedAci(); const ourAci = window.textsecure.storage.user.getCheckedAci();
await window.textsecure.storage.protocol.archiveSession( await signalProtocolStore.archiveSession(
new QualifiedAddress(ourAci, new Address(serviceId, 1)) new QualifiedAddress(ourAci, new Address(serviceId, 1))
); );
} }
+10 -10
View File
@@ -111,6 +111,7 @@ import {
} from '../types/ChatFolder.js'; } from '../types/ChatFolder.js';
import { deriveGroupID, deriveGroupSecretParams } from '../util/zkgroup.js'; import { deriveGroupID, deriveGroupSecretParams } from '../util/zkgroup.js';
import { chatFolderCleanupService } from './expiring/chatFolderCleanupService.js'; import { chatFolderCleanupService } from './expiring/chatFolderCleanupService.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
const { isEqual } = lodash; const { isEqual } = lodash;
@@ -135,7 +136,7 @@ export type MergeResultType = Readonly<{
}>; }>;
function toRecordVerified(verified: number): Proto.ContactRecord.IdentityState { function toRecordVerified(verified: number): Proto.ContactRecord.IdentityState {
const VERIFIED_ENUM = window.textsecure.storage.protocol.VerifiedStatus; const VERIFIED_ENUM = signalProtocolStore.VerifiedStatus;
const STATE_ENUM = Proto.ContactRecord.IdentityState; const STATE_ENUM = Proto.ContactRecord.IdentityState;
switch (verified) { switch (verified) {
@@ -151,7 +152,7 @@ function toRecordVerified(verified: number): Proto.ContactRecord.IdentityState {
function fromRecordVerified( function fromRecordVerified(
verified: Proto.ContactRecord.IdentityState verified: Proto.ContactRecord.IdentityState
): number { ): number {
const VERIFIED_ENUM = window.textsecure.storage.protocol.VerifiedStatus; const VERIFIED_ENUM = signalProtocolStore.VerifiedStatus;
const STATE_ENUM = Proto.ContactRecord.IdentityState; const STATE_ENUM = Proto.ContactRecord.IdentityState;
switch (verified) { switch (verified) {
@@ -283,7 +284,7 @@ export async function toContactRecord(
const serviceId = aci ?? pni; const serviceId = aci ?? pni;
const identityKey = serviceId const identityKey = serviceId
? await window.textsecure.storage.protocol.loadIdentityKey(serviceId) ? await signalProtocolStore.loadIdentityKey(serviceId)
: undefined; : undefined;
if (identityKey) { if (identityKey) {
contactRecord.identityKey = identityKey; contactRecord.identityKey = identityKey;
@@ -1376,12 +1377,11 @@ export async function mergeContactRecord(
} }
const newVerified = fromRecordVerified(identityState); const newVerified = fromRecordVerified(identityState);
const needsNotification = const needsNotification = await signalProtocolStore.updateIdentityAfterSync(
await window.textsecure.storage.protocol.updateIdentityAfterSync( serviceId,
serviceId, newVerified,
newVerified, contactRecord.identityKey
contactRecord.identityKey );
);
if (verified !== newVerified) { if (verified !== newVerified) {
details.push( details.push(
@@ -1392,7 +1392,7 @@ export async function mergeContactRecord(
conversation.set({ verified: newVerified }); conversation.set({ verified: newVerified });
} }
const VERIFIED_ENUM = window.textsecure.storage.protocol.VerifiedStatus; const VERIFIED_ENUM = signalProtocolStore.VerifiedStatus;
if (needsNotification) { if (needsNotification) {
details.push('adding a verified notification'); details.push('adding a verified notification');
await conversation.addVerifiedChange( await conversation.addVerifiedChange(
+1 -1
View File
@@ -200,7 +200,7 @@ import {
} from '../../util/syncIdentifiers.js'; } from '../../util/syncIdentifiers.js';
import { MAX_MESSAGE_COUNT } from '../../util/deleteForMe.types.js'; import { MAX_MESSAGE_COUNT } from '../../util/deleteForMe.types.js';
import { markCallHistoryReadInConversation } from './callHistory.js'; import { markCallHistoryReadInConversation } from './callHistory.js';
import type { CapabilitiesType } from '../../textsecure/WebAPI.js'; import type { CapabilitiesType } from '../../types/Capabilities.d.ts';
import { actions as searchActions } from './search.js'; import { actions as searchActions } from './search.js';
import type { SearchActionType } from './search.js'; import type { SearchActionType } from './search.js';
import { getNotificationTextForMessage } from '../../util/getNotificationTextForMessage.js'; import { getNotificationTextForMessage } from '../../util/getNotificationTextForMessage.js';
+2 -1
View File
@@ -29,6 +29,7 @@ import { useBoundActions } from '../../hooks/useBoundActions.js';
import { createLogger } from '../../logging/log.js'; import { createLogger } from '../../logging/log.js';
import { backupsService } from '../../services/backups/index.js'; import { backupsService } from '../../services/backups/index.js';
import OS from '../../util/os/osMain.js'; import OS from '../../util/os/osMain.js';
import { signalProtocolStore } from '../../SignalProtocolStore.js';
const log = createLogger('installer'); const log = createLogger('installer');
@@ -370,7 +371,7 @@ function finishInstall({
const shouldRetainData = Registration.everDone(); const shouldRetainData = Registration.everDone();
if (!shouldRetainData) { if (!shouldRetainData) {
try { try {
await window.textsecure.storage.protocol.removeAllData(); await signalProtocolStore.removeAllData();
} catch (error) { } catch (error) {
log.error( log.error(
'finishInstall: error clearing database', 'finishInstall: error clearing database',
@@ -14,6 +14,7 @@ import type {
} from '../types/ServiceId.js'; } from '../types/ServiceId.js';
import { generateAci, generatePni } from '../types/ServiceId.js'; import { generateAci, generatePni } from '../types/ServiceId.js';
import type { SafeCombineConversationsParams } from '../ConversationController.js'; import type { SafeCombineConversationsParams } from '../ConversationController.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
const ACI_1 = generateAci(); const ACI_1 = generateAci();
const ACI_2 = generateAci(); const ACI_2 = generateAci();
@@ -41,7 +42,7 @@ describe('ConversationController', () => {
window.ConversationController.reset(); window.ConversationController.reset();
await window.ConversationController.load(); await window.ConversationController.load();
await window.textsecure.storage.protocol.hydrateCaches(); await signalProtocolStore.hydrateCaches();
mergeOldAndNew = () => { mergeOldAndNew = () => {
throw new Error('mergeOldAndNew: Should not be called!'); throw new Error('mergeOldAndNew: Should not be called!');
+3 -2
View File
@@ -15,6 +15,7 @@ import { toAciObject } from '../util/ServiceId.js';
import { SignalService as Proto } from '../protobuf/index.js'; import { SignalService as Proto } from '../protobuf/index.js';
import * as Crypto from '../Crypto.js'; import * as Crypto from '../Crypto.js';
import { toBase64 } from '../Bytes.js'; import { toBase64 } from '../Bytes.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
describe('MessageReceiver', () => { describe('MessageReceiver', () => {
const someAci = generateAci(); const someAci = generateAci();
@@ -27,14 +28,14 @@ describe('MessageReceiver', () => {
oldAci = window.storage.user.getAci(); oldAci = window.storage.user.getAci();
oldDeviceId = window.storage.user.getDeviceId(); oldDeviceId = window.storage.user.getDeviceId();
await window.storage.user.setAciAndDeviceId(generateAci(), 2); await window.storage.user.setAciAndDeviceId(generateAci(), 2);
await window.storage.protocol.hydrateCaches(); await signalProtocolStore.hydrateCaches();
}); });
afterEach(async () => { afterEach(async () => {
if (oldAci !== undefined && oldDeviceId !== undefined) { if (oldAci !== undefined && oldDeviceId !== undefined) {
await window.storage.user.setAciAndDeviceId(oldAci, oldDeviceId); await window.storage.user.setAciAndDeviceId(oldAci, oldDeviceId);
} }
await window.storage.protocol.removeAllUnprocessed(); await signalProtocolStore.removeAllUnprocessed();
}); });
describe('connecting', () => { describe('connecting', () => {
+2 -2
View File
@@ -30,7 +30,7 @@ import {
generateKyberPreKey, generateKyberPreKey,
} from '../Curve.js'; } from '../Curve.js';
import type { SignalProtocolStore } from '../SignalProtocolStore.js'; import type { SignalProtocolStore } from '../SignalProtocolStore.js';
import { GLOBAL_ZONE } from '../SignalProtocolStore.js'; import { GLOBAL_ZONE, signalProtocolStore } from '../SignalProtocolStore.js';
import { Address } from '../types/Address.js'; import { Address } from '../types/Address.js';
import { QualifiedAddress } from '../types/QualifiedAddress.js'; import { QualifiedAddress } from '../types/QualifiedAddress.js';
import { generateAci, generatePni } from '../types/ServiceId.js'; import { generateAci, generatePni } from '../types/ServiceId.js';
@@ -152,7 +152,7 @@ describe('SignalProtocolStore', () => {
} }
before(async () => { before(async () => {
store = window.textsecure.storage.protocol; store = signalProtocolStore;
await store.hydrateCaches(); await store.hydrateCaches();
identityKey = IdentityKeyPair.generate(); identityKey = IdentityKeyPair.generate();
testKey = IdentityKeyPair.generate(); testKey = IdentityKeyPair.generate();
@@ -19,6 +19,7 @@ import {
generatePni, generatePni,
} from '../../types/ServiceId.js'; } from '../../types/ServiceId.js';
import { DAY } from '../../util/durations/index.js'; import { DAY } from '../../util/durations/index.js';
import { signalProtocolStore } from '../../SignalProtocolStore.js';
const { range } = lodash; const { range } = lodash;
@@ -40,9 +41,10 @@ describe('AccountManager', () => {
const server: any = {}; const server: any = {};
accountManager = new AccountManager(server); accountManager = new AccountManager(server);
const { storage } = window.textsecure; sandbox
sandbox.stub(storage.protocol, 'getIdentityKeyPair').returns(identityKey); .stub(signalProtocolStore, 'getIdentityKeyPair')
const { user } = storage; .returns(identityKey);
const { user } = window.textsecure.storage;
sandbox.stub(user, 'getAci').returns(ourAci); sandbox.stub(user, 'getAci').returns(ourAci);
sandbox.stub(user, 'getPni').returns(ourPni); sandbox.stub(user, 'getPni').returns(ourPni);
sandbox.stub(user, 'getServiceId').returns(ourAci); sandbox.stub(user, 'getServiceId').returns(ourAci);
@@ -83,20 +85,15 @@ describe('AccountManager', () => {
let signedPreKeys: Array<OuterSignedPrekeyType>; let signedPreKeys: Array<OuterSignedPrekeyType>;
beforeEach(async () => { beforeEach(async () => {
originalLoadSignedPreKeys = originalLoadSignedPreKeys = signalProtocolStore.loadSignedPreKeys;
window.textsecure.storage.protocol.loadSignedPreKeys; originalRemoveSignedPreKey = signalProtocolStore.removeSignedPreKeys;
originalRemoveSignedPreKey =
window.textsecure.storage.protocol.removeSignedPreKeys;
window.textsecure.storage.protocol.loadSignedPreKeys = () => signalProtocolStore.loadSignedPreKeys = () => signedPreKeys;
signedPreKeys;
// removeSignedPreKeys is updated per-test, below // removeSignedPreKeys is updated per-test, below
}); });
afterEach(() => { afterEach(() => {
window.textsecure.storage.protocol.loadSignedPreKeys = signalProtocolStore.loadSignedPreKeys = originalLoadSignedPreKeys;
originalLoadSignedPreKeys; signalProtocolStore.removeSignedPreKeys = originalRemoveSignedPreKey;
window.textsecure.storage.protocol.removeSignedPreKeys =
originalRemoveSignedPreKey;
}); });
it('keeps no keys if five or less, even if over a month old', () => { it('keeps no keys if five or less, even if over a month old', () => {
@@ -192,10 +189,7 @@ describe('AccountManager', () => {
]; ];
let removedKeys: Array<number> = []; let removedKeys: Array<number> = [];
window.textsecure.storage.protocol.removeSignedPreKeys = async ( signalProtocolStore.removeSignedPreKeys = async (_, keyIds) => {
_,
keyIds
) => {
removedKeys = removedKeys.concat(keyIds); removedKeys = removedKeys.concat(keyIds);
}; };
@@ -210,19 +204,15 @@ describe('AccountManager', () => {
let kyberPreKeys: Array<KyberPreKeyType>; let kyberPreKeys: Array<KyberPreKeyType>;
beforeEach(async () => { beforeEach(async () => {
originalLoadKyberPreKeys = originalLoadKyberPreKeys = signalProtocolStore.loadKyberPreKeys;
window.textsecure.storage.protocol.loadKyberPreKeys; originalRemoveKyberPreKey = signalProtocolStore.removeKyberPreKeys;
originalRemoveKyberPreKey =
window.textsecure.storage.protocol.removeKyberPreKeys;
window.textsecure.storage.protocol.loadKyberPreKeys = () => kyberPreKeys; signalProtocolStore.loadKyberPreKeys = () => kyberPreKeys;
// removeKyberPreKeys is updated per-test, below // removeKyberPreKeys is updated per-test, below
}); });
afterEach(() => { afterEach(() => {
window.textsecure.storage.protocol.loadKyberPreKeys = signalProtocolStore.loadKyberPreKeys = originalLoadKyberPreKeys;
originalLoadKyberPreKeys; signalProtocolStore.removeKyberPreKeys = originalRemoveKyberPreKey;
window.textsecure.storage.protocol.removeKyberPreKeys =
originalRemoveKyberPreKey;
}); });
it('keeps five keys even if over a month old', () => { it('keeps five keys even if over a month old', () => {
@@ -351,10 +341,7 @@ describe('AccountManager', () => {
]; ];
let removedKeys: Array<number> = []; let removedKeys: Array<number> = [];
window.textsecure.storage.protocol.removeKyberPreKeys = async ( signalProtocolStore.removeKyberPreKeys = async (_, keyIds) => {
_,
keyIds
) => {
removedKeys = removedKeys.concat(keyIds); removedKeys = removedKeys.concat(keyIds);
}; };
@@ -369,15 +356,15 @@ describe('AccountManager', () => {
let preKeys: Array<PreKeyType>; let preKeys: Array<PreKeyType>;
beforeEach(async () => { beforeEach(async () => {
originalLoadPreKeys = window.textsecure.storage.protocol.loadPreKeys; originalLoadPreKeys = signalProtocolStore.loadPreKeys;
originalRemovePreKeys = window.textsecure.storage.protocol.removePreKeys; originalRemovePreKeys = signalProtocolStore.removePreKeys;
window.textsecure.storage.protocol.loadPreKeys = () => preKeys; signalProtocolStore.loadPreKeys = () => preKeys;
// removePreKeys is updated per-test, below // removePreKeys is updated per-test, below
}); });
afterEach(() => { afterEach(() => {
window.textsecure.storage.protocol.loadPreKeys = originalLoadPreKeys; signalProtocolStore.loadPreKeys = originalLoadPreKeys;
window.textsecure.storage.protocol.removePreKeys = originalRemovePreKeys; signalProtocolStore.removePreKeys = originalRemovePreKeys;
}); });
it('keeps five keys even if over 90 days old, but all latest batch', () => { it('keeps five keys even if over 90 days old, but all latest batch', () => {
@@ -474,7 +461,7 @@ describe('AccountManager', () => {
]; ];
let removedKeys: Array<number> = []; let removedKeys: Array<number> = [];
window.textsecure.storage.protocol.removePreKeys = async (_, keyIds) => { signalProtocolStore.removePreKeys = async (_, keyIds) => {
removedKeys = removedKeys.concat(keyIds); removedKeys = removedKeys.concat(keyIds);
}; };
@@ -489,19 +476,15 @@ describe('AccountManager', () => {
let kyberPreKeys: Array<KyberPreKeyType>; let kyberPreKeys: Array<KyberPreKeyType>;
beforeEach(async () => { beforeEach(async () => {
originalLoadKyberPreKeys = originalLoadKyberPreKeys = signalProtocolStore.loadKyberPreKeys;
window.textsecure.storage.protocol.loadKyberPreKeys; originalRemoveKyberPreKeys = signalProtocolStore.removeKyberPreKeys;
originalRemoveKyberPreKeys =
window.textsecure.storage.protocol.removeKyberPreKeys;
window.textsecure.storage.protocol.loadKyberPreKeys = () => kyberPreKeys; signalProtocolStore.loadKyberPreKeys = () => kyberPreKeys;
// removeKyberPreKeys is updated per-test, below // removeKyberPreKeys is updated per-test, below
}); });
afterEach(() => { afterEach(() => {
window.textsecure.storage.protocol.loadKyberPreKeys = signalProtocolStore.loadKyberPreKeys = originalLoadKyberPreKeys;
originalLoadKyberPreKeys; signalProtocolStore.removeKyberPreKeys = originalRemoveKyberPreKeys;
window.textsecure.storage.protocol.removeKyberPreKeys =
originalRemoveKyberPreKeys;
}); });
it('keeps five keys even if over 90 days old', () => { it('keeps five keys even if over 90 days old', () => {
@@ -606,10 +589,7 @@ describe('AccountManager', () => {
]; ];
let removedKeys: Array<number> = []; let removedKeys: Array<number> = [];
window.textsecure.storage.protocol.removeKyberPreKeys = async ( signalProtocolStore.removeKyberPreKeys = async (_, keyIds) => {
_,
keyIds
) => {
removedKeys = removedKeys.concat(keyIds); removedKeys = removedKeys.concat(keyIds);
}; };
@@ -13,6 +13,7 @@ import AccountManager from '../../textsecure/AccountManager.js';
import { ServiceIdKind } from '../../types/ServiceId.js'; import { ServiceIdKind } from '../../types/ServiceId.js';
import { normalizeAci } from '../../util/normalizeAci.js'; import { normalizeAci } from '../../util/normalizeAci.js';
import { DataWriter } from '../../sql/Client.js'; import { DataWriter } from '../../sql/Client.js';
import { signalProtocolStore } from '../../SignalProtocolStore.js';
const { textsecure } = window; const { textsecure } = window;
@@ -31,16 +32,13 @@ describe('Key generation', function (this: Mocha.Suite) {
function itStoresPreKey(keyId: number): void { function itStoresPreKey(keyId: number): void {
it(`prekey ${keyId} is valid`, async () => { it(`prekey ${keyId} is valid`, async () => {
const keyPair = await textsecure.storage.protocol.loadPreKey( const keyPair = await signalProtocolStore.loadPreKey(ourServiceId, keyId);
ourServiceId,
keyId
);
assert(keyPair, `PreKey ${keyId} not found`); assert(keyPair, `PreKey ${keyId} not found`);
}); });
} }
function itStoresKyberPreKey(keyId: number): void { function itStoresKyberPreKey(keyId: number): void {
it(`kyber pre key ${keyId} is valid`, async () => { it(`kyber pre key ${keyId} is valid`, async () => {
const key = await textsecure.storage.protocol.loadKyberPreKey( const key = await signalProtocolStore.loadKyberPreKey(
ourServiceId, ourServiceId,
keyId keyId
); );
@@ -51,7 +49,7 @@ describe('Key generation', function (this: Mocha.Suite) {
async function validateResultPreKey( async function validateResultPreKey(
resultKey: UploadPreKeyType resultKey: UploadPreKeyType
): Promise<void> { ): Promise<void> {
const keyPair = await textsecure.storage.protocol.loadPreKey( const keyPair = await signalProtocolStore.loadPreKey(
ourServiceId, ourServiceId,
resultKey.keyId resultKey.keyId
); );
@@ -65,9 +63,9 @@ describe('Key generation', function (this: Mocha.Suite) {
} }
before(async () => { before(async () => {
await textsecure.storage.protocol.clearPreKeyStore(); await signalProtocolStore.clearPreKeyStore();
await textsecure.storage.protocol.clearKyberPreKeyStore(); await signalProtocolStore.clearKyberPreKeyStore();
await textsecure.storage.protocol.clearSignedPreKeysStore(); await signalProtocolStore.clearSignedPreKeysStore();
const keyPair = generateKeyPair(); const keyPair = generateKeyPair();
await textsecure.storage.put('identityKeyMap', { await textsecure.storage.put('identityKeyMap', {
@@ -78,13 +76,13 @@ describe('Key generation', function (this: Mocha.Suite) {
}); });
await textsecure.storage.user.setAciAndDeviceId(ourServiceId, 1); await textsecure.storage.user.setAciAndDeviceId(ourServiceId, 1);
await textsecure.storage.protocol.hydrateCaches(); await signalProtocolStore.hydrateCaches();
}); });
after(async () => { after(async () => {
await textsecure.storage.protocol.clearPreKeyStore(); await signalProtocolStore.clearPreKeyStore();
await textsecure.storage.protocol.clearKyberPreKeyStore(); await signalProtocolStore.clearKyberPreKeyStore();
await textsecure.storage.protocol.clearSignedPreKeysStore(); await signalProtocolStore.clearSignedPreKeysStore();
await DataWriter.removeAll(); await DataWriter.removeAll();
await window.storage.fetch(); await window.storage.fetch();
@@ -209,7 +207,7 @@ describe('Key generation', function (this: Mocha.Suite) {
}); });
it('does not generate a third last resort prekey', async () => { it('does not generate a third last resort prekey', async () => {
const keyId = 3 * count + 3; const keyId = 3 * count + 3;
const key = await textsecure.storage.protocol.loadKyberPreKey( const key = await signalProtocolStore.loadKyberPreKey(
ourServiceId, ourServiceId,
keyId keyId
); );
@@ -217,7 +215,7 @@ describe('Key generation', function (this: Mocha.Suite) {
}); });
it('does not generate a third signed prekey', async () => { it('does not generate a third signed prekey', async () => {
const keyId = 3; const keyId = 3;
const keyPair = await textsecure.storage.protocol.loadSignedPreKey( const keyPair = await signalProtocolStore.loadSignedPreKey(
ourServiceId, ourServiceId,
keyId keyId
); );
+46 -47
View File
@@ -72,6 +72,7 @@ import { getRelativePath, createName } from '../util/attachmentPath.js';
import { isLinkAndSyncEnabled } from '../util/isLinkAndSyncEnabled.js'; import { isLinkAndSyncEnabled } from '../util/isLinkAndSyncEnabled.js';
import { getMessageQueueTime } from '../util/getMessageQueueTime.js'; import { getMessageQueueTime } from '../util/getMessageQueueTime.js';
import { canAttemptRemoteBackupDownload } from '../util/isBackupEnabled.js'; import { canAttemptRemoteBackupDownload } from '../util/isBackupEnabled.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
const { isNumber, omit, orderBy } = lodash; const { isNumber, omit, orderBy } = lodash;
@@ -281,8 +282,7 @@ export default class AccountManager extends EventTarget {
async decryptDeviceName(base64: string): Promise<string> { async decryptDeviceName(base64: string): Promise<string> {
const ourAci = window.textsecure.storage.user.getCheckedAci(); const ourAci = window.textsecure.storage.user.getCheckedAci();
const identityKey = const identityKey = signalProtocolStore.getIdentityKeyPair(ourAci);
window.textsecure.storage.protocol.getIdentityKeyPair(ourAci);
if (!identityKey) { if (!identityKey) {
throw new Error('decryptDeviceName: No identity key pair!'); throw new Error('decryptDeviceName: No identity key pair!');
} }
@@ -316,7 +316,7 @@ export default class AccountManager extends EventTarget {
} }
const { storage } = window.textsecure; const { storage } = window.textsecure;
const deviceName = storage.user.getDeviceName(); const deviceName = storage.user.getDeviceName();
const identityKeyPair = storage.protocol.getIdentityKeyPair( const identityKeyPair = signalProtocolStore.getIdentityKeyPair(
storage.user.getCheckedAci() storage.user.getCheckedAci()
); );
strictAssert( strictAssert(
@@ -376,11 +376,9 @@ export default class AccountManager extends EventTarget {
} }
#getIdentityKeyOrThrow(ourServiceId: ServiceIdString): KeyPairType { #getIdentityKeyOrThrow(ourServiceId: ServiceIdString): KeyPairType {
const { storage } = window.textsecure;
const store = storage.protocol;
let identityKey: KeyPairType | undefined; let identityKey: KeyPairType | undefined;
try { try {
identityKey = store.getIdentityKeyPair(ourServiceId); identityKey = signalProtocolStore.getIdentityKeyPair(ourServiceId);
} catch (error) { } catch (error) {
const errorText = Errors.toLogFormat(error); const errorText = Errors.toLogFormat(error);
throw new Error( throw new Error(
@@ -403,7 +401,6 @@ export default class AccountManager extends EventTarget {
window.textsecure.storage.user.getCheckedServiceId(serviceIdKind); window.textsecure.storage.user.getCheckedServiceId(serviceIdKind);
const logId = `AccountManager.generateNewPreKeys(${serviceIdKind})`; const logId = `AccountManager.generateNewPreKeys(${serviceIdKind})`;
const { storage } = window.textsecure; const { storage } = window.textsecure;
const store = storage.protocol;
const startId = getNextKeyId(serviceIdKind, PRE_KEY_ID_KEY); const startId = getNextKeyId(serviceIdKind, PRE_KEY_ID_KEY);
log.info(`${logId}: Generating ${count} new keys starting at ${startId}`); log.info(`${logId}: Generating ${count} new keys starting at ${startId}`);
@@ -420,7 +417,7 @@ export default class AccountManager extends EventTarget {
} }
await Promise.all([ await Promise.all([
store.storePreKeys(ourServiceId, toSave), signalProtocolStore.storePreKeys(ourServiceId, toSave),
storage.put(PRE_KEY_ID_KEY[serviceIdKind], startId + count), storage.put(PRE_KEY_ID_KEY[serviceIdKind], startId + count),
]); ]);
@@ -435,8 +432,6 @@ export default class AccountManager extends EventTarget {
count = PRE_KEY_GEN_BATCH_SIZE count = PRE_KEY_GEN_BATCH_SIZE
): Promise<Array<UploadKyberPreKeyType>> { ): Promise<Array<UploadKyberPreKeyType>> {
const logId = `AccountManager.generateNewKyberPreKeys(${serviceIdKind})`; const logId = `AccountManager.generateNewKyberPreKeys(${serviceIdKind})`;
const { storage } = window.textsecure;
const store = storage.protocol;
const startId = getNextKeyId(serviceIdKind, KYBER_KEY_ID_KEY); const startId = getNextKeyId(serviceIdKind, KYBER_KEY_ID_KEY);
log.info(`${logId}: Generating ${count} new keys starting at ${startId}`); log.info(`${logId}: Generating ${count} new keys starting at ${startId}`);
@@ -447,6 +442,8 @@ export default class AccountManager extends EventTarget {
); );
} }
const { storage } = window.textsecure;
const ourServiceId = storage.user.getCheckedServiceId(serviceIdKind); const ourServiceId = storage.user.getCheckedServiceId(serviceIdKind);
const identityKey = this.#getIdentityKeyOrThrow(ourServiceId); const identityKey = this.#getIdentityKeyOrThrow(ourServiceId);
@@ -471,7 +468,7 @@ export default class AccountManager extends EventTarget {
} }
await Promise.all([ await Promise.all([
store.storeKyberPreKeys(ourServiceId, toSave), signalProtocolStore.storeKyberPreKeys(ourServiceId, toSave),
storage.put(KYBER_KEY_ID_KEY[serviceIdKind], startId + count), storage.put(KYBER_KEY_ID_KEY[serviceIdKind], startId + count),
]); ]);
@@ -645,9 +642,8 @@ export default class AccountManager extends EventTarget {
window.textsecure.storage.user.getCheckedServiceId(serviceIdKind); window.textsecure.storage.user.getCheckedServiceId(serviceIdKind);
const identityKey = this.#getIdentityKeyOrThrow(ourServiceId); const identityKey = this.#getIdentityKeyOrThrow(ourServiceId);
const logId = `AccountManager.maybeUpdateSignedPreKey(${serviceIdKind}, ${ourServiceId})`; const logId = `AccountManager.maybeUpdateSignedPreKey(${serviceIdKind}, ${ourServiceId})`;
const store = window.textsecure.storage.protocol;
const keys = await store.loadSignedPreKeys(ourServiceId); const keys = await signalProtocolStore.loadSignedPreKeys(ourServiceId);
const sortedKeys = orderBy(keys, ['created_at'], ['desc']); const sortedKeys = orderBy(keys, ['created_at'], ['desc']);
const confirmedKeys = sortedKeys.filter(key => key.confirmed); const confirmedKeys = sortedKeys.filter(key => key.confirmed);
const mostRecent = confirmedKeys[0]; const mostRecent = confirmedKeys[0];
@@ -677,7 +673,11 @@ export default class AccountManager extends EventTarget {
const key = await this.#generateSignedPreKey(serviceIdKind, identityKey); const key = await this.#generateSignedPreKey(serviceIdKind, identityKey);
log.info(`${logId}: Saving new signed prekey`, key.keyId); log.info(`${logId}: Saving new signed prekey`, key.keyId);
await store.storeSignedPreKey(ourServiceId, key.keyId, key.keyPair); await signalProtocolStore.storeSignedPreKey(
ourServiceId,
key.keyId,
key.keyPair
);
return signedPreKeyToUploadSignedPreKey(key); return signedPreKeyToUploadSignedPreKey(key);
} }
@@ -715,9 +715,10 @@ export default class AccountManager extends EventTarget {
window.textsecure.storage.user.getCheckedServiceId(serviceIdKind); window.textsecure.storage.user.getCheckedServiceId(serviceIdKind);
const identityKey = this.#getIdentityKeyOrThrow(ourServiceId); const identityKey = this.#getIdentityKeyOrThrow(ourServiceId);
const logId = `maybeUpdateLastResortKyberKey(${serviceIdKind}, ${ourServiceId})`; const logId = `maybeUpdateLastResortKyberKey(${serviceIdKind}, ${ourServiceId})`;
const store = window.textsecure.storage.protocol;
const keys = store.loadKyberPreKeys(ourServiceId, { isLastResort: true }); const keys = signalProtocolStore.loadKyberPreKeys(ourServiceId, {
isLastResort: true,
});
const sortedKeys = orderBy(keys, ['createdAt'], ['desc']); const sortedKeys = orderBy(keys, ['createdAt'], ['desc']);
const confirmedKeys = sortedKeys.filter(key => key.isConfirmed); const confirmedKeys = sortedKeys.filter(key => key.isConfirmed);
const mostRecent = confirmedKeys[0]; const mostRecent = confirmedKeys[0];
@@ -751,7 +752,7 @@ export default class AccountManager extends EventTarget {
log.info(`${logId}: Saving new last resort prekey`, record.id()); log.info(`${logId}: Saving new last resort prekey`, record.id());
const key = kyberPreKeyToStoredSignedPreKey(record, ourServiceId); const key = kyberPreKeyToStoredSignedPreKey(record, ourServiceId);
await store.storeKyberPreKeys(ourServiceId, [key]); await signalProtocolStore.storeKyberPreKeys(ourServiceId, [key]);
return kyberPreKeyToUploadSignedPreKey(record); return kyberPreKeyToUploadSignedPreKey(record);
} }
@@ -760,10 +761,9 @@ export default class AccountManager extends EventTarget {
async _cleanSignedPreKeys(serviceIdKind: ServiceIdKind): Promise<void> { async _cleanSignedPreKeys(serviceIdKind: ServiceIdKind): Promise<void> {
const ourServiceId = const ourServiceId =
window.textsecure.storage.user.getCheckedServiceId(serviceIdKind); window.textsecure.storage.user.getCheckedServiceId(serviceIdKind);
const store = window.textsecure.storage.protocol;
const logId = `AccountManager.cleanSignedPreKeys(${serviceIdKind})`; const logId = `AccountManager.cleanSignedPreKeys(${serviceIdKind})`;
const allKeys = store.loadSignedPreKeys(ourServiceId); const allKeys = signalProtocolStore.loadSignedPreKeys(ourServiceId);
const sortedKeys = orderBy(allKeys, ['created_at'], ['desc']); const sortedKeys = orderBy(allKeys, ['created_at'], ['desc']);
const confirmed = sortedKeys.filter(key => key.confirmed); const confirmed = sortedKeys.filter(key => key.confirmed);
const unconfirmed = sortedKeys.filter(key => !key.confirmed); const unconfirmed = sortedKeys.filter(key => !key.confirmed);
@@ -805,7 +805,7 @@ export default class AccountManager extends EventTarget {
}); });
if (toDelete.length > 0) { if (toDelete.length > 0) {
log.info(`${logId}: Removing ${toDelete.length} signed prekeys`); log.info(`${logId}: Removing ${toDelete.length} signed prekeys`);
await store.removeSignedPreKeys(ourServiceId, toDelete); await signalProtocolStore.removeSignedPreKeys(ourServiceId, toDelete);
} }
} }
@@ -813,10 +813,9 @@ export default class AccountManager extends EventTarget {
async _cleanLastResortKeys(serviceIdKind: ServiceIdKind): Promise<void> { async _cleanLastResortKeys(serviceIdKind: ServiceIdKind): Promise<void> {
const ourServiceId = const ourServiceId =
window.textsecure.storage.user.getCheckedServiceId(serviceIdKind); window.textsecure.storage.user.getCheckedServiceId(serviceIdKind);
const store = window.textsecure.storage.protocol;
const logId = `AccountManager.cleanLastResortKeys(${serviceIdKind})`; const logId = `AccountManager.cleanLastResortKeys(${serviceIdKind})`;
const allKeys = store.loadKyberPreKeys(ourServiceId, { const allKeys = signalProtocolStore.loadKyberPreKeys(ourServiceId, {
isLastResort: true, isLastResort: true,
}); });
const sortedKeys = orderBy(allKeys, ['createdAt'], ['desc']); const sortedKeys = orderBy(allKeys, ['createdAt'], ['desc']);
@@ -862,17 +861,16 @@ export default class AccountManager extends EventTarget {
}); });
if (toDelete.length > 0) { if (toDelete.length > 0) {
log.info(`${logId}: Removing ${toDelete.length} last resort keys`); log.info(`${logId}: Removing ${toDelete.length} last resort keys`);
await store.removeKyberPreKeys(ourServiceId, toDelete); await signalProtocolStore.removeKyberPreKeys(ourServiceId, toDelete);
} }
} }
async _cleanPreKeys(serviceIdKind: ServiceIdKind): Promise<void> { async _cleanPreKeys(serviceIdKind: ServiceIdKind): Promise<void> {
const store = window.textsecure.storage.protocol;
const logId = `AccountManager.cleanPreKeys(${serviceIdKind})`; const logId = `AccountManager.cleanPreKeys(${serviceIdKind})`;
const ourServiceId = const ourServiceId =
window.textsecure.storage.user.getCheckedServiceId(serviceIdKind); window.textsecure.storage.user.getCheckedServiceId(serviceIdKind);
const preKeys = store.loadPreKeys(ourServiceId); const preKeys = signalProtocolStore.loadPreKeys(ourServiceId);
const toDelete: Array<number> = []; const toDelete: Array<number> = [];
const sortedKeys = orderBy(preKeys, ['createdAt'], ['desc']); const sortedKeys = orderBy(preKeys, ['createdAt'], ['desc']);
@@ -890,17 +888,16 @@ export default class AccountManager extends EventTarget {
log.info(`${logId}: ${sortedKeys.length} total prekeys`); log.info(`${logId}: ${sortedKeys.length} total prekeys`);
if (toDelete.length > 0) { if (toDelete.length > 0) {
log.info(`${logId}: Removing ${toDelete.length} obsolete prekeys`); log.info(`${logId}: Removing ${toDelete.length} obsolete prekeys`);
await store.removePreKeys(ourServiceId, toDelete); await signalProtocolStore.removePreKeys(ourServiceId, toDelete);
} }
} }
async _cleanKyberPreKeys(serviceIdKind: ServiceIdKind): Promise<void> { async _cleanKyberPreKeys(serviceIdKind: ServiceIdKind): Promise<void> {
const store = window.textsecure.storage.protocol;
const logId = `AccountManager.cleanKyberPreKeys(${serviceIdKind})`; const logId = `AccountManager.cleanKyberPreKeys(${serviceIdKind})`;
const ourServiceId = const ourServiceId =
window.textsecure.storage.user.getCheckedServiceId(serviceIdKind); window.textsecure.storage.user.getCheckedServiceId(serviceIdKind);
const preKeys = store.loadKyberPreKeys(ourServiceId, { const preKeys = signalProtocolStore.loadKyberPreKeys(ourServiceId, {
isLastResort: false, isLastResort: false,
}); });
const toDelete: Array<number> = []; const toDelete: Array<number> = [];
@@ -920,7 +917,7 @@ export default class AccountManager extends EventTarget {
log.info(`${logId}: ${sortedKeys.length} total prekeys`); log.info(`${logId}: ${sortedKeys.length} total prekeys`);
if (toDelete.length > 0) { if (toDelete.length > 0) {
log.info(`${logId}: Removing ${toDelete.length} kyber keys`); log.info(`${logId}: Removing ${toDelete.length} kyber keys`);
await store.removeKyberPreKeys(ourServiceId, toDelete); await signalProtocolStore.removeKyberPreKeys(ourServiceId, toDelete);
} }
} }
@@ -1004,7 +1001,7 @@ export default class AccountManager extends EventTarget {
} }
try { try {
await storage.protocol.removeAllData(); await signalProtocolStore.removeAllData();
log.info('createAccount: Successfully deleted previous data'); log.info('createAccount: Successfully deleted previous data');
cleanStart = true; cleanStart = true;
@@ -1016,7 +1013,7 @@ export default class AccountManager extends EventTarget {
} }
} else { } else {
log.info('createAccount: Erasing configuration'); log.info('createAccount: Erasing configuration');
await storage.protocol.removeAllConfiguration(); await signalProtocolStore.removeAllConfiguration();
} }
await senderCertificateService.clear(); await senderCertificateService.clear();
@@ -1174,18 +1171,18 @@ export default class AccountManager extends EventTarget {
const identityAttrs = { const identityAttrs = {
firstUse: true, firstUse: true,
timestamp: Date.now(), timestamp: Date.now(),
verified: storage.protocol.VerifiedStatus.VERIFIED, verified: signalProtocolStore.VerifiedStatus.VERIFIED,
nonblockingApproval: true, nonblockingApproval: true,
}; };
// update our own identity key, which may have changed // update our own identity key, which may have changed
// if we're relinking after a reinstall on the master device // if we're relinking after a reinstall on the master device
await Promise.all([ await Promise.all([
storage.protocol.saveIdentityWithAttributes(ourAci, { signalProtocolStore.saveIdentityWithAttributes(ourAci, {
...identityAttrs, ...identityAttrs,
publicKey: aciKeyPair.publicKey.serialize(), publicKey: aciKeyPair.publicKey.serialize(),
}), }),
storage.protocol.saveIdentityWithAttributes(ourPni, { signalProtocolStore.saveIdentityWithAttributes(ourPni, {
...identityAttrs, ...identityAttrs,
publicKey: pniKeyPair.publicKey.serialize(), publicKey: pniKeyPair.publicKey.serialize(),
}), }),
@@ -1242,24 +1239,22 @@ export default class AccountManager extends EventTarget {
const regionCode = getRegionCodeForNumber(number); const regionCode = getRegionCodeForNumber(number);
await storage.put('regionCode', regionCode); await storage.put('regionCode', regionCode);
await storage.protocol.hydrateCaches(); await signalProtocolStore.hydrateCaches();
const store = storage.protocol; await signalProtocolStore.storeSignedPreKey(
await store.storeSignedPreKey(
ourAci, ourAci,
aciSignedPreKey.keyId, aciSignedPreKey.keyId,
aciSignedPreKey.keyPair aciSignedPreKey.keyPair
); );
await store.storeSignedPreKey( await signalProtocolStore.storeSignedPreKey(
ourPni, ourPni,
pniSignedPreKey.keyId, pniSignedPreKey.keyId,
pniSignedPreKey.keyPair pniSignedPreKey.keyPair
); );
await store.storeKyberPreKeys(ourAci, [ await signalProtocolStore.storeKyberPreKeys(ourAci, [
kyberPreKeyToStoredSignedPreKey(aciPqLastResortPreKey, ourAci), kyberPreKeyToStoredSignedPreKey(aciPqLastResortPreKey, ourAci),
]); ]);
await store.storeKyberPreKeys(ourPni, [ await signalProtocolStore.storeKyberPreKeys(ourPni, [
kyberPreKeyToStoredSignedPreKey(pniPqLastResortPreKey, ourPni), kyberPreKeyToStoredSignedPreKey(pniPqLastResortPreKey, ourPni),
]); ]);
@@ -1319,13 +1314,14 @@ export default class AccountManager extends EventTarget {
const ourServiceId = const ourServiceId =
window.textsecure.storage.user.getCheckedServiceId(serviceIdKind); window.textsecure.storage.user.getCheckedServiceId(serviceIdKind);
const logId = `AccountManager.confirmKeys(${serviceIdKind})`; const logId = `AccountManager.confirmKeys(${serviceIdKind})`;
const { storage } = window.textsecure;
const store = storage.protocol;
const updatedAt = Date.now(); const updatedAt = Date.now();
if (signedPreKey) { if (signedPreKey) {
log.info(`${logId}: confirming signed prekey key`, signedPreKey.keyId); log.info(`${logId}: confirming signed prekey key`, signedPreKey.keyId);
await store.confirmSignedPreKey(ourServiceId, signedPreKey.keyId); await signalProtocolStore.confirmSignedPreKey(
ourServiceId,
signedPreKey.keyId
);
await window.storage.put( await window.storage.put(
SIGNED_PRE_KEY_UPDATE_TIME_KEY[serviceIdKind], SIGNED_PRE_KEY_UPDATE_TIME_KEY[serviceIdKind],
updatedAt updatedAt
@@ -1339,7 +1335,10 @@ export default class AccountManager extends EventTarget {
`${logId}: confirming last resort key`, `${logId}: confirming last resort key`,
pqLastResortPreKey.keyId pqLastResortPreKey.keyId
); );
await store.confirmKyberPreKey(ourServiceId, pqLastResortPreKey.keyId); await signalProtocolStore.confirmKyberPreKey(
ourServiceId,
pqLastResortPreKey.keyId
);
await window.storage.put( await window.storage.put(
LAST_RESORT_KEY_UPDATE_TIME_KEY[serviceIdKind], LAST_RESORT_KEY_UPDATE_TIME_KEY[serviceIdKind],
updatedAt updatedAt
@@ -1398,14 +1397,14 @@ export default class AccountManager extends EventTarget {
log.info(`${logId}: updating from ${oldPni}`); log.info(`${logId}: updating from ${oldPni}`);
if (oldPni) { if (oldPni) {
await storage.protocol.removeOurOldPni(oldPni); await signalProtocolStore.removeOurOldPni(oldPni);
await window.ConversationController.clearShareMyPhoneNumber(); await window.ConversationController.clearShareMyPhoneNumber();
} }
await storage.user.setPni(pni); await storage.user.setPni(pni);
if (keyMaterial) { if (keyMaterial) {
await storage.protocol.updateOurPniKeyMaterial(pni, keyMaterial); await signalProtocolStore.updateOurPniKeyMaterial(pni, keyMaterial);
// Intentionally not awaiting since this is processed on encrypted queue // Intentionally not awaiting since this is processed on encrypted queue
// of MessageReceiver. Note that `maybeUpdateKeys` runs on the queue so // of MessageReceiver. Note that `maybeUpdateKeys` runs on the queue so
+13 -14
View File
@@ -69,6 +69,7 @@ import { isAciString } from '../util/isAciString.js';
import { calling } from '../services/calling.js'; import { calling } from '../services/calling.js';
import { retryPlaceholders } from '../services/retryPlaceholders.js'; import { retryPlaceholders } from '../services/retryPlaceholders.js';
import * as Errors from '../types/errors.js'; import * as Errors from '../types/errors.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
import { SignalService as Proto } from '../protobuf/index.js'; import { SignalService as Proto } from '../protobuf/index.js';
import { deriveGroupFields, MASTER_KEY_LENGTH } from '../groups.js'; import { deriveGroupFields, MASTER_KEY_LENGTH } from '../groups.js';
@@ -936,7 +937,7 @@ export default class MessageReceiver
try { try {
const { id } = item; const { id } = item;
await this.#storage.protocol.removeUnprocessed(id); await signalProtocolStore.removeUnprocessed(id);
} catch (deleteError) { } catch (deleteError) {
log.error( log.error(
'queueCached error deleting item', 'queueCached error deleting item',
@@ -973,15 +974,13 @@ export default class MessageReceiver
async *#getAllFromCache(): AsyncIterable<Array<UnprocessedType>> { async *#getAllFromCache(): AsyncIterable<Array<UnprocessedType>> {
log.info('getAllFromCache'); log.info('getAllFromCache');
const ids = await this.#storage.protocol.getAllUnprocessedIds(); const ids = await signalProtocolStore.getAllUnprocessedIds();
log.info(`getAllFromCache - ${ids.length} unprocessed`); log.info(`getAllFromCache - ${ids.length} unprocessed`);
for (const batch of chunk(ids, 1000)) { for (const batch of chunk(ids, 1000)) {
log.info(`getAllFromCache - yielding batch of ${batch.length}`); log.info(`getAllFromCache - yielding batch of ${batch.length}`);
yield this.#storage.protocol.getUnprocessedByIdsAndIncrementAttempts( yield signalProtocolStore.getUnprocessedByIdsAndIncrementAttempts(batch);
batch
);
} }
log.info(`getAllFromCache - done retrieving ${ids.length} unprocessed`); log.info(`getAllFromCache - done retrieving ${ids.length} unprocessed`);
} }
@@ -997,7 +996,7 @@ export default class MessageReceiver
}> }>
> = []; > = [];
const storageProtocol = this.#storage.protocol; const storageProtocol = signalProtocolStore;
try { try {
const zone = new Zone('decryptAndCacheBatch', { const zone = new Zone('decryptAndCacheBatch', {
@@ -1189,7 +1188,7 @@ export default class MessageReceiver
} }
async #cacheRemoveBatch(items: Array<string>): Promise<void> { async #cacheRemoveBatch(items: Array<string>): Promise<void> {
await this.#storage.protocol.removeUnprocessed(items); await signalProtocolStore.removeUnprocessed(items);
} }
#removeFromCache(envelope: ProcessedEnvelope): void { #removeFromCache(envelope: ProcessedEnvelope): void {
@@ -1750,7 +1749,7 @@ export default class MessageReceiver
Address.create(sealedSenderIdentifier, sealedSenderSourceDevice) Address.create(sealedSenderIdentifier, sealedSenderSourceDevice)
); );
const plaintext = await this.#storage.protocol.enqueueSenderKeyJob( const plaintext = await signalProtocolStore.enqueueSenderKeyJob(
address, address,
() => () =>
groupDecrypt( groupDecrypt(
@@ -1792,7 +1791,7 @@ export default class MessageReceiver
messageContent.msgType() === CiphertextMessageType.PreKey messageContent.msgType() === CiphertextMessageType.PreKey
? PreKeySignalMessage.deserialize(messageContent.contents()) ? PreKeySignalMessage.deserialize(messageContent.contents())
: SignalMessage.deserialize(messageContent.contents()); : SignalMessage.deserialize(messageContent.contents());
const plaintext = await this.#storage.protocol.enqueueSessionJob( const plaintext = await signalProtocolStore.enqueueSessionJob(
address, address,
() => { () => {
if (message instanceof PreKeySignalMessage) { if (message instanceof PreKeySignalMessage) {
@@ -1887,7 +1886,7 @@ export default class MessageReceiver
} }
const signalMessage = SignalMessage.deserialize(ciphertext); const signalMessage = SignalMessage.deserialize(ciphertext);
const plaintext = await this.#storage.protocol.enqueueSessionJob( const plaintext = await signalProtocolStore.enqueueSessionJob(
address, address,
async () => async () =>
this.#unpad( this.#unpad(
@@ -1916,7 +1915,7 @@ export default class MessageReceiver
} }
const preKeySignalMessage = PreKeySignalMessage.deserialize(ciphertext); const preKeySignalMessage = PreKeySignalMessage.deserialize(ciphertext);
const plaintext = await this.#storage.protocol.enqueueSessionJob( const plaintext = await signalProtocolStore.enqueueSessionJob(
address, address,
async () => async () =>
this.#unpad( this.#unpad(
@@ -2689,7 +2688,7 @@ export default class MessageReceiver
Address.create(sourceServiceId, sourceDevice) Address.create(sourceServiceId, sourceDevice)
); );
await this.#storage.protocol.enqueueSenderKeyJob( await signalProtocolStore.enqueueSenderKeyJob(
address, address,
() => () =>
processSenderKeyDistributionMessage( processSenderKeyDistributionMessage(
@@ -2722,7 +2721,7 @@ export default class MessageReceiver
strictAssert(isAciString(aci), `${logId}: invalid ACI`); strictAssert(isAciString(aci), `${logId}: invalid ACI`);
strictAssert(isPniString(pni), `${logId}: invalid PNI`); strictAssert(isPniString(pni), `${logId}: invalid PNI`);
const isValid = await this.#storage.protocol.verifyAlternateIdentity({ const isValid = await signalProtocolStore.verifyAlternateIdentity({
aci, aci,
pni, pni,
signature, signature,
@@ -4034,7 +4033,7 @@ export default class MessageReceiver
logUnexpectedUrgentValue(envelope, 'resetSession'); logUnexpectedUrgentValue(envelope, 'resetSession');
await this.#storage.protocol.archiveAllSessions(theirServiceId); await signalProtocolStore.archiveAllSessions(theirServiceId);
} }
#processDecrypted( #processDecrypted(
+7 -6
View File
@@ -45,6 +45,7 @@ import { createLogger } from '../logging/log.js';
import type { GroupSendToken } from '../types/GroupSendEndorsements.js'; import type { GroupSendToken } from '../types/GroupSendEndorsements.js';
import { isSignalServiceId } from '../util/isSignalConversation.js'; import { isSignalServiceId } from '../util/isSignalConversation.js';
import * as Bytes from '../Bytes.js'; import * as Bytes from '../Bytes.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
const { reject } = lodash; const { reject } = lodash;
@@ -274,7 +275,7 @@ export default class OutgoingMessage {
): () => Promise<void> { ): () => Promise<void> {
return async () => { return async () => {
const ourAci = window.textsecure.storage.user.getCheckedAci(); const ourAci = window.textsecure.storage.user.getCheckedAci();
const deviceIds = await window.textsecure.storage.protocol.getDeviceIds({ const deviceIds = await signalProtocolStore.getDeviceIds({
ourServiceId: ourAci, ourServiceId: ourAci,
serviceId, serviceId,
}); });
@@ -452,7 +453,7 @@ export default class OutgoingMessage {
new Address(serviceId, destinationDeviceId) new Address(serviceId, destinationDeviceId)
); );
return window.textsecure.storage.protocol.enqueueSessionJob<MessageType>( return signalProtocolStore.enqueueSessionJob<MessageType>(
address, address,
async () => { async () => {
const protocolAddress = ProtocolAddress.new( const protocolAddress = ProtocolAddress.new(
@@ -622,7 +623,7 @@ export default class OutgoingMessage {
} else { } else {
p = Promise.all( p = Promise.all(
(response.staleDevices || []).map(async (deviceId: number) => { (response.staleDevices || []).map(async (deviceId: number) => {
await window.textsecure.storage.protocol.archiveSession( await signalProtocolStore.archiveSession(
new QualifiedAddress(ourAci, new Address(serviceId, deviceId)) new QualifiedAddress(ourAci, new Address(serviceId, deviceId))
); );
}) })
@@ -655,7 +656,7 @@ export default class OutgoingMessage {
); );
log.info('closing all sessions for', serviceId); log.info('closing all sessions for', serviceId);
window.textsecure.storage.protocol.archiveAllSessions(serviceId).then( signalProtocolStore.archiveAllSessions(serviceId).then(
() => { () => {
throw error; throw error;
}, },
@@ -687,7 +688,7 @@ export default class OutgoingMessage {
await Promise.all( await Promise.all(
deviceIdsToRemove.map(async deviceId => { deviceIdsToRemove.map(async deviceId => {
await window.textsecure.storage.protocol.archiveSession( await signalProtocolStore.archiveSession(
new QualifiedAddress(ourAci, new Address(serviceId, deviceId)) new QualifiedAddress(ourAci, new Address(serviceId, deviceId))
); );
}) })
@@ -706,7 +707,7 @@ export default class OutgoingMessage {
try { try {
const ourAci = window.textsecure.storage.user.getCheckedAci(); const ourAci = window.textsecure.storage.user.getCheckedAci();
const deviceIds = await window.textsecure.storage.protocol.getDeviceIds({ const deviceIds = await signalProtocolStore.getDeviceIds({
ourServiceId: ourAci, ourServiceId: ourAci,
serviceId, serviceId,
}); });
+22 -27
View File
@@ -15,9 +15,9 @@ import {
SenderKeyDistributionMessage, SenderKeyDistributionMessage,
} from '@signalapp/libsignal-client'; } from '@signalapp/libsignal-client';
import { GLOBAL_ZONE, signalProtocolStore } from '../SignalProtocolStore.js';
import { DataWriter } from '../sql/Client.js'; import { DataWriter } from '../sql/Client.js';
import type { ConversationModel } from '../models/conversations.js'; import type { ConversationModel } from '../models/conversations.js';
import { GLOBAL_ZONE } from '../SignalProtocolStore.js';
import { assertDev, strictAssert } from '../util/assert.js'; import { assertDev, strictAssert } from '../util/assert.js';
import { parseIntOrThrow } from '../util/parseIntOrThrow.js'; import { parseIntOrThrow } from '../util/parseIntOrThrow.js';
import { Address } from '../types/Address.js'; import { Address } from '../types/Address.js';
@@ -1368,9 +1368,7 @@ export default class MessageSender {
} }
if (isPniString(serviceId)) { if (isPniString(serviceId)) {
const pniIdentityKey = const pniIdentityKey =
await window.textsecure.storage.protocol.loadIdentityKey( await signalProtocolStore.loadIdentityKey(serviceId);
serviceId
);
if (pniIdentityKey) { if (pniIdentityKey) {
status.destinationPniIdentityKey = pniIdentityKey; status.destinationPniIdentityKey = pniIdentityKey;
} }
@@ -2297,33 +2295,30 @@ export default class MessageSender {
); );
const senderKeyDistributionMessage = const senderKeyDistributionMessage =
await window.textsecure.storage.protocol.enqueueSenderKeyJob( await signalProtocolStore.enqueueSenderKeyJob(address, async () => {
address, const senderKeyStore = new SenderKeys({
async () => { ourServiceId: ourAci,
const senderKeyStore = new SenderKeys({ zone: GLOBAL_ZONE,
ourServiceId: ourAci, });
zone: GLOBAL_ZONE,
});
if (throwIfNotInDatabase) { if (throwIfNotInDatabase) {
const key = await senderKeyStore.getSenderKey( const key = await senderKeyStore.getSenderKey(
protocolAddress,
distributionId
);
if (!key) {
throw new NoSenderKeyError(
`getSenderKeyDistributionMessage: Distribution ${distributionId} was not in database as expected`
);
}
}
return SenderKeyDistributionMessage.create(
protocolAddress, protocolAddress,
distributionId, distributionId
senderKeyStore
); );
if (!key) {
throw new NoSenderKeyError(
`getSenderKeyDistributionMessage: Distribution ${distributionId} was not in database as expected`
);
}
} }
);
return SenderKeyDistributionMessage.create(
protocolAddress,
distributionId,
senderKeyStore
);
});
log.info( log.info(
`getSenderKeyDistributionMessage: Building ${distributionId} with timestamp ${timestamp}` `getSenderKeyDistributionMessage: Building ${distributionId} with timestamp ${timestamp}`
-15
View File
@@ -8,9 +8,7 @@ import type {
import { User } from './storage/User.js'; import { User } from './storage/User.js';
import { Blocked } from './storage/Blocked.js'; import { Blocked } from './storage/Blocked.js';
import { assertDev } from '../util/assert.js';
import { DataReader, DataWriter } from '../sql/Client.js'; import { DataReader, DataWriter } from '../sql/Client.js';
import type { SignalProtocolStore } from '../SignalProtocolStore.js';
import { createLogger } from '../logging/log.js'; import { createLogger } from '../logging/log.js';
const log = createLogger('Storage'); const log = createLogger('Storage');
@@ -30,7 +28,6 @@ export class Storage implements StorageInterface {
#ready = false; #ready = false;
#readyCallbacks: Array<() => void> = []; #readyCallbacks: Array<() => void> = [];
#items: Partial<Access> = Object.create(null); #items: Partial<Access> = Object.create(null);
#privProtocol: SignalProtocolStore | undefined;
constructor() { constructor() {
this.user = new User(this); this.user = new User(this);
@@ -39,18 +36,6 @@ export class Storage implements StorageInterface {
window.storage = this; window.storage = this;
} }
get protocol(): SignalProtocolStore {
assertDev(
this.#privProtocol !== undefined,
'SignalProtocolStore not initialized'
);
return this.#privProtocol;
}
set protocol(value: SignalProtocolStore) {
this.#privProtocol = value;
}
// `StorageInterface` implementation // `StorageInterface` implementation
public get<K extends keyof Access, V extends Access[K]>( public get<K extends keyof Access, V extends Access[K]>(
+4 -10
View File
@@ -36,6 +36,10 @@ import { createProxyAgent } from '../util/createProxyAgent.js';
import type { ProxyAgent } from '../util/createProxyAgent.js'; import type { ProxyAgent } from '../util/createProxyAgent.js';
import type { FetchFunctionType } from '../util/uploads/tusProtocol.js'; import type { FetchFunctionType } from '../util/uploads/tusProtocol.js';
import { VerificationTransport } from '../types/VerificationTransport.js'; import { VerificationTransport } from '../types/VerificationTransport.js';
import type {
CapabilitiesType,
CapabilitiesUploadType,
} from '../types/Capabilities.d.ts';
import type { HeaderListType } from '../types/WebAPI.d.ts'; import type { HeaderListType } from '../types/WebAPI.d.ts';
import { ZERO_ACCESS_KEY } from '../types/SealedSender.js'; import { ZERO_ACCESS_KEY } from '../types/SealedSender.js';
import { toLogFormat } from '../types/errors.js'; import { toLogFormat } from '../types/errors.js';
@@ -851,16 +855,6 @@ export type WebAPIConnectType = {
connect: (options: WebAPIConnectOptionsType) => WebAPIType; connect: (options: WebAPIConnectOptionsType) => WebAPIType;
}; };
// When updating this make sure to update `observedCapabilities` type in
// ts/types/Storage.d.ts
export type CapabilitiesType = {
attachmentBackfill: boolean;
};
export type CapabilitiesUploadType = {
attachmentBackfill: true;
spqr: true;
};
type StickerPackManifestType = Uint8Array; type StickerPackManifestType = Uint8Array;
export type GroupCredentialType = { export type GroupCredentialType = {
+9 -10
View File
@@ -22,6 +22,7 @@ import { isRecord } from '../util/isRecord.js';
import type { GroupSendToken } from '../types/GroupSendEndorsements.js'; import type { GroupSendToken } from '../types/GroupSendEndorsements.js';
import { HTTPError } from '../types/HTTPError.js'; import { HTTPError } from '../types/HTTPError.js';
import { onFailedToSendWithEndorsements } from '../util/groupSendEndorsements.js'; import { onFailedToSendWithEndorsements } from '../util/groupSendEndorsements.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
const log = createLogger('getKeysForServiceId'); const log = createLogger('getKeysForServiceId');
@@ -47,7 +48,7 @@ export async function getKeysForServiceId(
}; };
} catch (error) { } catch (error) {
if (error instanceof HTTPError && error.code === 404) { if (error instanceof HTTPError && error.code === 404) {
await window.textsecure.storage.protocol.archiveAllSessions(serviceId); await signalProtocolStore.archiveAllSessions(serviceId);
throw new UnregisteredUserError(serviceId, error); throw new UnregisteredUserError(serviceId, error);
} }
@@ -176,15 +177,13 @@ async function handleServerKeys(
); );
try { try {
await window.textsecure.storage.protocol.enqueueSessionJob( await signalProtocolStore.enqueueSessionJob(address, () =>
address, processPreKeyBundle(
() => preKeyBundle,
processPreKeyBundle( protocolAddress,
preKeyBundle, sessionStore,
protocolAddress, identityKeyStore
sessionStore, )
identityKeyStore
)
); );
} catch (error) { } catch (error) {
if ( if (
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
// When updating this make sure to update `observedCapabilities` type in
// ts/types/Storage.d.ts
export type CapabilitiesType = {
attachmentBackfill: boolean;
};
export type CapabilitiesUploadType = {
attachmentBackfill: true;
spqr: true;
};
+2 -1
View File
@@ -3,6 +3,7 @@
import { createLogger } from '../logging/log.js'; import { createLogger } from '../logging/log.js';
import { constantTimeEqual } from '../Crypto.js'; import { constantTimeEqual } from '../Crypto.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
import { strictAssert } from './assert.js'; import { strictAssert } from './assert.js';
const log = createLogger('checkOurPniIdentityKey'); const log = createLogger('checkOurPniIdentityKey');
@@ -19,7 +20,7 @@ export async function checkOurPniIdentityKey(): Promise<void> {
return; return;
} }
const localKeyPair = await window.storage.protocol.getIdentityKeyPair(ourPni); const localKeyPair = await signalProtocolStore.getIdentityKeyPair(ourPni);
if (!localKeyPair) { if (!localKeyPair) {
log.warn(`no local key pair for ${ourPni}, unlinking`); log.warn(`no local key pair for ${ourPni}, unlinking`);
window.Whisper.events.emit('unlinkAndDisconnect'); window.Whisper.events.emit('unlinkAndDisconnect');
+4 -9
View File
@@ -7,6 +7,7 @@ import type {
} from '../model-types.d.ts'; } from '../model-types.d.ts';
import { combineNames } from './combineNames.js'; import { combineNames } from './combineNames.js';
import { getRegionCodeForNumber } from './libphonenumberUtil.js'; import { getRegionCodeForNumber } from './libphonenumberUtil.js';
import { instance, PhoneNumberFormat } from './libphonenumberInstance.js';
import { isDirectConversation } from './whatTypeOfConversation.js'; import { isDirectConversation } from './whatTypeOfConversation.js';
import { getE164 } from './getE164.js'; import { getE164 } from './getE164.js';
@@ -158,18 +159,12 @@ export function getNumber(
export function renderNumber(e164: string): string | undefined { export function renderNumber(e164: string): string | undefined {
try { try {
const parsedNumber = window.libphonenumberInstance.parse(e164); const parsedNumber = instance.parse(e164);
const regionCode = getRegionCodeForNumber(e164); const regionCode = getRegionCodeForNumber(e164);
if (regionCode === window.storage.get('regionCode')) { if (regionCode === window.storage.get('regionCode')) {
return window.libphonenumberInstance.format( return instance.format(parsedNumber, PhoneNumberFormat.NATIONAL);
parsedNumber,
window.libphonenumberFormat.NATIONAL
);
} }
return window.libphonenumberInstance.format( return instance.format(parsedNumber, PhoneNumberFormat.INTERNATIONAL);
parsedNumber,
window.libphonenumberFormat.INTERNATIONAL
);
} catch (e) { } catch (e) {
return undefined; return undefined;
} }
+4 -3
View File
@@ -9,6 +9,7 @@ import lodash from 'lodash';
import type PQueue from 'p-queue'; import type PQueue from 'p-queue';
import * as Bytes from '../Bytes.js'; import * as Bytes from '../Bytes.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
import { DataReader, DataWriter } from '../sql/Client.js'; import { DataReader, DataWriter } from '../sql/Client.js';
import { isProduction } from './version.js'; import { isProduction } from './version.js';
import { strictAssert } from './assert.js'; import { strictAssert } from './assert.js';
@@ -360,13 +361,13 @@ async function archiveSessionOnMatch({
ourAci, ourAci,
Address.create(requesterAci, requesterDevice) Address.create(requesterAci, requesterDevice)
); );
const session = await window.textsecure.storage.protocol.loadSession(address); const session = await signalProtocolStore.loadSession(address);
if (session && session.currentRatchetKeyMatches(ratchetKey)) { if (session && session.currentRatchetKeyMatches(ratchetKey)) {
log.info( log.info(
'archiveSessionOnMatch: Matching device and ratchetKey, archiving session' 'archiveSessionOnMatch: Matching device and ratchetKey, archiving session'
); );
await window.textsecure.storage.protocol.archiveSession(address); await signalProtocolStore.archiveSession(address);
return true; return true;
} }
@@ -720,7 +721,7 @@ function scheduleSessionReset(senderAci: AciString, senderDevice: number) {
lightSessionResetQueue.add(async () => { lightSessionResetQueue.add(async () => {
const ourAci = window.textsecure.storage.user.getCheckedAci(); const ourAci = window.textsecure.storage.user.getCheckedAci();
await window.textsecure.storage.protocol.lightSessionReset( await signalProtocolStore.lightSessionReset(
new QualifiedAddress(ourAci, Address.create(senderAci, senderDevice)) new QualifiedAddress(ourAci, Address.create(senderAci, senderDevice))
); );
}) })
+3 -2
View File
@@ -8,6 +8,7 @@ import { assertDev } from './assert.js';
import { uuidToBytes } from './uuidToBytes.js'; import { uuidToBytes } from './uuidToBytes.js';
import { createLogger } from '../logging/log.js'; import { createLogger } from '../logging/log.js';
import type { SafetyNumberType } from '../types/safetyNumber.js'; import type { SafetyNumberType } from '../types/safetyNumber.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
import { isAciString } from './isAciString.js'; import { isAciString } from './isAciString.js';
const log = createLogger('safetyNumber'); const log = createLogger('safetyNumber');
@@ -27,14 +28,14 @@ export async function generateSafetyNumber(
const { storage } = window.textsecure; const { storage } = window.textsecure;
const ourAci = storage.user.getCheckedAci(); const ourAci = storage.user.getCheckedAci();
const us = storage.protocol.getIdentityRecord(ourAci); const us = signalProtocolStore.getIdentityRecord(ourAci);
const ourKeyBuffer = us ? us.publicKey : null; const ourKeyBuffer = us ? us.publicKey : null;
const theirAci = isAciString(contact.serviceId) const theirAci = isAciString(contact.serviceId)
? contact.serviceId ? contact.serviceId
: undefined; : undefined;
const them = theirAci const them = theirAci
? await storage.protocol.getOrMigrateIdentityRecord(theirAci) ? await signalProtocolStore.getOrMigrateIdentityRecord(theirAci)
: undefined; : undefined;
const theirKeyBuffer = them?.publicKey; const theirKeyBuffer = them?.publicKey;
+10 -11
View File
@@ -14,6 +14,7 @@ import {
SenderCertificate, SenderCertificate,
UnidentifiedSenderMessageContent, UnidentifiedSenderMessageContent,
} from '@signalapp/libsignal-client'; } from '@signalapp/libsignal-client';
import { signalProtocolStore, GLOBAL_ZONE } from '../SignalProtocolStore.js';
import { senderCertificateService } from '../services/senderCertificate.js'; import { senderCertificateService } from '../services/senderCertificate.js';
import type { SendLogCallbackType } from '../textsecure/OutgoingMessage.js'; import type { SendLogCallbackType } from '../textsecure/OutgoingMessage.js';
import { import {
@@ -65,7 +66,6 @@ import { SignalService as Proto } from '../protobuf/index.js';
import { strictAssert } from './assert.js'; import { strictAssert } from './assert.js';
import { createLogger } from '../logging/log.js'; import { createLogger } from '../logging/log.js';
import { GLOBAL_ZONE } from '../SignalProtocolStore.js';
import { waitForAll } from './waitForAll.js'; import { waitForAll } from './waitForAll.js';
import type { GroupSendEndorsementState } from './groupSendEndorsements.js'; import type { GroupSendEndorsementState } from './groupSendEndorsements.js';
import { import {
@@ -355,7 +355,7 @@ export async function sendToGroupViaSenderKey(
// 2. Fetch all devices we believe we'll be sending to // 2. Fetch all devices we believe we'll be sending to
const ourAci = window.textsecure.storage.user.getCheckedAci(); const ourAci = window.textsecure.storage.user.getCheckedAci();
const { devices: currentDevices, emptyServiceIds } = const { devices: currentDevices, emptyServiceIds } =
await window.textsecure.storage.protocol.getOpenDevices(ourAci, recipients); await signalProtocolStore.getOpenDevices(ourAci, recipients);
let groupSendEndorsementState: GroupSendEndorsementState | null = null; let groupSendEndorsementState: GroupSendEndorsementState | null = null;
if (groupId != null && !story) { if (groupId != null && !story) {
@@ -770,7 +770,7 @@ export async function resetSenderKey(
}); });
const ourAci = window.storage.user.getCheckedAci(); const ourAci = window.storage.user.getCheckedAci();
await window.textsecure.storage.protocol.removeSenderKey( await signalProtocolStore.removeSenderKey(
new QualifiedAddress(ourAci, ourAddress), new QualifiedAddress(ourAci, ourAddress),
distributionId distributionId
); );
@@ -950,7 +950,7 @@ async function markServiceIdUnregistered(serviceId: ServiceIdString) {
conversation.setUnregistered(); conversation.setUnregistered();
await DataWriter.updateConversation(conversation.attributes); await DataWriter.updateConversation(conversation.attributes);
await window.textsecure.storage.protocol.archiveAllSessions(serviceId); await signalProtocolStore.archiveAllSessions(serviceId);
} }
function isServiceIdRegistered(serviceId: ServiceIdString) { function isServiceIdRegistered(serviceId: ServiceIdString) {
@@ -992,7 +992,7 @@ async function handle409Response(
await waitForAll({ await waitForAll({
tasks: devices.extraDevices.map(deviceId => async () => { tasks: devices.extraDevices.map(deviceId => async () => {
await window.textsecure.storage.protocol.archiveSession( await signalProtocolStore.archiveSession(
new QualifiedAddress(ourAci, Address.create(uuid, deviceId)) new QualifiedAddress(ourAci, Address.create(uuid, deviceId))
); );
}), }),
@@ -1032,7 +1032,7 @@ async function handle410Response(
// First, archive our existing sessions with these devices // First, archive our existing sessions with these devices
await waitForAll({ await waitForAll({
tasks: devices.staleDevices.map(deviceId => async () => { tasks: devices.staleDevices.map(deviceId => async () => {
await window.textsecure.storage.protocol.archiveSession( await signalProtocolStore.archiveSession(
new QualifiedAddress(ourAci, Address.create(uuid, deviceId)) new QualifiedAddress(ourAci, Address.create(uuid, deviceId))
); );
}), }),
@@ -1151,11 +1151,10 @@ async function encryptForSenderKey({
}); });
const message = padMessage(contentMessage); const message = padMessage(contentMessage);
const ciphertextMessage = const ciphertextMessage = await signalProtocolStore.enqueueSenderKeyJob(
await window.textsecure.storage.protocol.enqueueSenderKeyJob( new QualifiedAddress(ourAci, ourAddress),
new QualifiedAddress(ourAci, ourAddress), () => groupEncrypt(sender, distributionId, senderKeyStore, message)
() => groupEncrypt(sender, distributionId, senderKeyStore, message) );
);
const groupIdBuffer = groupId ? Bytes.fromBase64(groupId) : null; const groupIdBuffer = groupId ? Bytes.fromBase64(groupId) : null;
const senderCertificateObject = await senderCertificateService.get( const senderCertificateObject = await senderCertificateService.get(
+2 -2
View File
@@ -5,6 +5,7 @@ import { createLogger } from '../logging/log.js';
import { isNotNil } from './isNotNil.js'; import { isNotNil } from './isNotNil.js';
import { updateIdentityKey } from '../services/profiles.js'; import { updateIdentityKey } from '../services/profiles.js';
import type { ServiceIdString } from '../types/ServiceId.js'; import type { ServiceIdString } from '../types/ServiceId.js';
import { signalProtocolStore } from '../SignalProtocolStore.js';
import * as Bytes from '../Bytes.js'; import * as Bytes from '../Bytes.js';
const log = createLogger('verifyStoryListMembers'); const log = createLogger('verifyStoryListMembers');
@@ -25,8 +26,7 @@ export async function verifyStoryListMembers(
const elements = await Promise.all( const elements = await Promise.all(
serviceIds.map(async serviceId => { serviceIds.map(async serviceId => {
const fingerprint = const fingerprint = await signalProtocolStore.getFingerprint(serviceId);
await window.textsecure.storage.protocol.getFingerprint(serviceId);
if (!fingerprint) { if (!fingerprint) {
log.warn('no fingerprint found for serviceId=', serviceId); log.warn('no fingerprint found for serviceId=', serviceId);
-29
View File
@@ -8,7 +8,6 @@ import type { Store } from 'redux';
import type { SystemPreferences } from 'electron'; import type { SystemPreferences } from 'electron';
import type PQueue from 'p-queue/dist.js'; import type PQueue from 'p-queue/dist.js';
import type { assert } from 'chai'; import type { assert } from 'chai';
import googleLibphonenumber from 'google-libphonenumber';
import type { MochaOptions } from 'mocha'; import type { MochaOptions } from 'mocha';
import type { textsecure } from './textsecure/index.js'; import type { textsecure } from './textsecure/index.js';
@@ -18,7 +17,6 @@ import type {
IPCRequest as IPCChallengeRequest, IPCRequest as IPCChallengeRequest,
} from './challenge.js'; } from './challenge.js';
import type AccountManager from './textsecure/AccountManager.js'; import type AccountManager from './textsecure/AccountManager.js';
import type { WebAPIConnectType } from './textsecure/WebAPI.js';
import type { OSType } from './util/os/shared.js'; import type { OSType } from './util/os/shared.js';
import type { import type {
LocalizerType, LocalizerType,
@@ -29,7 +27,6 @@ import type { Receipt } from './types/Receipt.js';
import type { ConversationController } from './ConversationController.js'; import type { ConversationController } from './ConversationController.js';
import type { ReduxActions } from './state/types.js'; import type { ReduxActions } from './state/types.js';
import type { BatcherType } from './util/batcher.js'; import type { BatcherType } from './util/batcher.js';
import type { SignalProtocolStore } from './SignalProtocolStore.js';
import type { ScreenShareStatus } from './types/Calling.js'; import type { ScreenShareStatus } from './types/Calling.js';
import type { MessageCache } from './services/MessageCache.js'; import type { MessageCache } from './services/MessageCache.js';
import type { StateType } from './state/reducer.js'; import type { StateType } from './state/reducer.js';
@@ -45,8 +42,6 @@ import type { WindowsNotificationData } from './services/notifications.js';
import type { QueryStatsOptions } from './sql/main.js'; import type { QueryStatsOptions } from './sql/main.js';
import type { SocketStatuses } from './textsecure/SocketManager.js'; import type { SocketStatuses } from './textsecure/SocketManager.js';
const { PhoneNumber, PhoneNumberFormat } = googleLibphonenumber;
export { Long } from 'long'; export { Long } from 'long';
export type IPCType = { export type IPCType = {
@@ -164,13 +159,6 @@ declare global {
// We want to extend various globals, so we need to use interfaces. // We want to extend various globals, so we need to use interfaces.
/* eslint-disable no-restricted-syntax */ /* eslint-disable no-restricted-syntax */
interface Window { interface Window {
// Used in Sticker Creator to create proper paths to emoji images
ROOT_PATH?: string;
// Used for sticker creator localization
localeMessages: { [key: string]: { message: string } };
openArtCreator: (opts: { username: string; password: string }) => void;
enterKeyboardMode: () => void; enterKeyboardMode: () => void;
enterMouseMode: () => void; enterMouseMode: () => void;
getAccountManager: () => AccountManager; getAccountManager: () => AccountManager;
@@ -191,18 +179,11 @@ declare global {
isAfterVersion: (version: string, anotherVersion: string) => boolean; isAfterVersion: (version: string, anotherVersion: string) => boolean;
isBeforeVersion: (version: string, anotherVersion: string) => boolean; isBeforeVersion: (version: string, anotherVersion: string) => boolean;
initialTheme?: ThemeType; initialTheme?: ThemeType;
libphonenumberInstance: {
parse: (number: string) => PhoneNumber;
getRegionCodeForNumber: (number: PhoneNumber) => string | undefined;
format: (number: PhoneNumber, format: PhoneNumberFormat) => string;
};
libphonenumberFormat: typeof PhoneNumberFormat;
nodeSetImmediate: typeof setImmediate; nodeSetImmediate: typeof setImmediate;
platform: string; platform: string;
preloadedImages: Array<HTMLImageElement>; preloadedImages: Array<HTMLImageElement>;
setImmediate: typeof setImmediate; setImmediate: typeof setImmediate;
sendChallengeRequest: (request: IPCChallengeRequest) => void; sendChallengeRequest: (request: IPCChallengeRequest) => void;
showKeyboardShortcuts: () => void;
storage: Storage; storage: Storage;
systemTheme: SystemThemeType; systemTheme: SystemThemeType;
@@ -217,12 +198,8 @@ declare global {
ConversationController: ConversationController; ConversationController: ConversationController;
Events: IPCEventsType; Events: IPCEventsType;
FontFace: typeof FontFace;
MessageCache: MessageCache; MessageCache: MessageCache;
SignalProtocolStore: typeof SignalProtocolStore;
WebAPI: WebAPIConnectType;
Whisper: WhisperType; Whisper: WhisperType;
getSignalProtocolStore: () => SignalProtocolStore;
i18n: LocalizerType; i18n: LocalizerType;
// Note: used in background.html, and not type-checked // Note: used in background.html, and not type-checked
startApp: () => void; startApp: () => void;
@@ -287,12 +264,6 @@ declare global {
interface SharedArrayBuffer { interface SharedArrayBuffer {
__arrayBuffer: never; __arrayBuffer: never;
} }
interface Set<T> {
// Needed until TS upgrade
difference<U>(other: ReadonlySet<U>): Set<T>;
symmetricDifference<U>(other: ReadonlySet<U>): Set<T>;
}
} }
export type WhisperType = { export type WhisperType = {
-24
View File
@@ -1,7 +1,6 @@
// Copyright 2022 Signal Messenger, LLC // Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import googleLibphonenumber from 'google-libphonenumber';
import * as moment from 'moment'; import * as moment from 'moment';
// @ts-expect-error -- no types // @ts-expect-error -- no types
import 'moment/min/locales.min.js'; import 'moment/min/locales.min.js';
@@ -15,8 +14,6 @@ import { createLogger } from '../../logging/log.js';
import { SignalContext } from '../context.js'; import { SignalContext } from '../context.js';
import * as Attachments from './attachments.js'; import * as Attachments from './attachments.js';
const { PhoneNumberUtil, PhoneNumberFormat } = googleLibphonenumber;
const log = createLogger('phase2-dependencies'); const log = createLogger('phase2-dependencies');
initializeLogging(); initializeLogging();
@@ -26,27 +23,6 @@ window.textsecure = textsecure;
const { config } = window.SignalContext; const { config } = window.SignalContext;
window.WebAPI = window.textsecure.WebAPI.initialize({
chatServiceUrl: config.serverUrl,
storageUrl: config.storageUrl,
updatesUrl: config.updatesUrl,
resourcesUrl: config.resourcesUrl,
cdnUrlObject: {
0: config.cdnUrl0,
2: config.cdnUrl2,
3: config.cdnUrl3,
},
certificateAuthority: config.certificateAuthority,
contentProxyUrl: config.contentProxyUrl,
proxyUrl: config.proxyUrl,
version: config.version,
disableIPv6: config.disableIPv6,
stripePublishableKey: config.stripePublishableKey,
});
window.libphonenumberInstance = PhoneNumberUtil.getInstance();
window.libphonenumberFormat = PhoneNumberFormat;
const { resolvedTranslationsLocale, preferredSystemLocales, localeOverride } = const { resolvedTranslationsLocale, preferredSystemLocales, localeOverride } =
config; config;
-3
View File
@@ -14,7 +14,6 @@ import chaiAsPromised from 'chai-as-promised';
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
import { reporters, type MochaOptions } from 'mocha'; import { reporters, type MochaOptions } from 'mocha';
import { getSignalProtocolStore } from '../../SignalProtocolStore.js';
import { initMessageCleanup } from '../../services/messageStateCleanup.js'; import { initMessageCleanup } from '../../services/messageStateCleanup.js';
import { initializeMessageCounter } from '../../util/incrementMessageCounter.js'; import { initializeMessageCounter } from '../../util/incrementMessageCounter.js';
import { initializeRedux } from '../../state/initializeRedux.js'; import { initializeRedux } from '../../state/initializeRedux.js';
@@ -165,5 +164,3 @@ window.testUtilities = {
} }
}, },
}; };
window.getSignalProtocolStore = getSignalProtocolStore;