UUID-keyed lookups in SignalProtocolStore

This commit is contained in:
Fedor Indutny 2021-09-09 19:38:11 -07:00 committed by GitHub
parent 6323aedd9b
commit c7e7d55af4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 2094 additions and 1447 deletions

View file

@ -23,28 +23,42 @@ import {
Uuid,
} from '@signalapp/signal-client';
import { freezePreKey, freezeSignedPreKey } from './SignalProtocolStore';
import { Address } from './types/Address';
import { QualifiedAddress } from './types/QualifiedAddress';
import type { UUID } from './types/UUID';
import { typedArrayToArrayBuffer } from './Crypto';
import { Zone } from './util/Zone';
function encodedNameFromAddress(address: ProtocolAddress): string {
function encodeAddress(address: ProtocolAddress): Address {
const name = address.name();
const deviceId = address.deviceId();
const encodedName = `${name}.${deviceId}`;
return encodedName;
return Address.create(name, deviceId);
}
export type SessionsOptions = {
readonly zone?: Zone;
};
function toQualifiedAddress(
ourUuid: UUID,
address: ProtocolAddress
): QualifiedAddress {
return new QualifiedAddress(ourUuid, encodeAddress(address));
}
export type SessionsOptions = Readonly<{
ourUuid: UUID;
zone?: Zone;
}>;
export class Sessions extends SessionStore {
private readonly ourUuid: UUID;
private readonly zone: Zone | undefined;
constructor(options: SessionsOptions = {}) {
constructor({ ourUuid, zone }: SessionsOptions) {
super();
this.zone = options.zone;
this.ourUuid = ourUuid;
this.zone = zone;
}
async saveSession(
@ -52,16 +66,16 @@ export class Sessions extends SessionStore {
record: SessionRecord
): Promise<void> {
await window.textsecure.storage.protocol.storeSession(
encodedNameFromAddress(address),
toQualifiedAddress(this.ourUuid, address),
record,
{ zone: this.zone }
);
}
async getSession(name: ProtocolAddress): Promise<SessionRecord | null> {
const encodedName = encodedNameFromAddress(name);
const encodedAddress = toQualifiedAddress(this.ourUuid, name);
const record = await window.textsecure.storage.protocol.loadSession(
encodedName,
encodedAddress,
{ zone: this.zone }
);
@ -71,27 +85,36 @@ export class Sessions extends SessionStore {
async getExistingSessions(
addresses: Array<ProtocolAddress>
): Promise<Array<SessionRecord>> {
const encodedAddresses = addresses.map(encodedNameFromAddress);
const encodedAddresses = addresses.map(addr =>
toQualifiedAddress(this.ourUuid, addr)
);
return window.textsecure.storage.protocol.loadSessions(encodedAddresses, {
zone: this.zone,
});
}
}
export type IdentityKeysOptions = {
readonly zone?: Zone;
};
export type IdentityKeysOptions = Readonly<{
ourUuid: UUID;
zone?: Zone;
}>;
export class IdentityKeys extends IdentityKeyStore {
private readonly ourUuid: UUID;
private readonly zone: Zone | undefined;
constructor({ zone }: IdentityKeysOptions = {}) {
constructor({ ourUuid, zone }: IdentityKeysOptions) {
super();
this.ourUuid = ourUuid;
this.zone = zone;
}
async getIdentityKey(): Promise<PrivateKey> {
const keyPair = await window.textsecure.storage.protocol.getIdentityKeyPair();
const keyPair = await window.textsecure.storage.protocol.getIdentityKeyPair(
this.ourUuid
);
if (!keyPair) {
throw new Error('IdentityKeyStore/getIdentityKey: No identity key!');
}
@ -99,7 +122,9 @@ export class IdentityKeys extends IdentityKeyStore {
}
async getLocalRegistrationId(): Promise<number> {
const id = await window.textsecure.storage.protocol.getLocalRegistrationId();
const id = await window.textsecure.storage.protocol.getLocalRegistrationId(
this.ourUuid
);
if (!isNumber(id)) {
throw new Error(
'IdentityKeyStore/getLocalRegistrationId: No registration id!'
@ -109,9 +134,9 @@ export class IdentityKeys extends IdentityKeyStore {
}
async getIdentity(address: ProtocolAddress): Promise<PublicKey | null> {
const encodedName = encodedNameFromAddress(address);
const encodedAddress = encodeAddress(address);
const key = await window.textsecure.storage.protocol.loadIdentityKey(
encodedName
encodedAddress.uuid
);
if (!key) {
@ -122,13 +147,13 @@ export class IdentityKeys extends IdentityKeyStore {
}
async saveIdentity(name: ProtocolAddress, key: PublicKey): Promise<boolean> {
const encodedName = encodedNameFromAddress(name);
const encodedAddress = encodeAddress(name);
const publicKey = typedArrayToArrayBuffer(key.serialize());
// Pass `zone` to let `saveIdentity` archive sibling sessions when identity
// key changes.
return window.textsecure.storage.protocol.saveIdentity(
encodedName,
encodedAddress,
publicKey,
false,
{ zone: this.zone }
@ -140,27 +165,42 @@ export class IdentityKeys extends IdentityKeyStore {
key: PublicKey,
direction: Direction
): Promise<boolean> {
const encodedName = encodedNameFromAddress(name);
const encodedAddress = encodeAddress(name);
const publicKey = typedArrayToArrayBuffer(key.serialize());
return window.textsecure.storage.protocol.isTrustedIdentity(
encodedName,
encodedAddress,
publicKey,
direction
);
}
}
export type PreKeysOptions = Readonly<{
ourUuid: UUID;
}>;
export class PreKeys extends PreKeyStore {
private readonly ourUuid: UUID;
constructor({ ourUuid }: PreKeysOptions) {
super();
this.ourUuid = ourUuid;
}
async savePreKey(id: number, record: PreKeyRecord): Promise<void> {
await window.textsecure.storage.protocol.storePreKey(
this.ourUuid,
id,
freezePreKey(record)
);
}
async getPreKey(id: number): Promise<PreKeyRecord> {
const preKey = await window.textsecure.storage.protocol.loadPreKey(id);
const preKey = await window.textsecure.storage.protocol.loadPreKey(
this.ourUuid,
id
);
if (preKey === undefined) {
throw new Error(`getPreKey: PreKey ${id} not found`);
@ -170,17 +210,28 @@ export class PreKeys extends PreKeyStore {
}
async removePreKey(id: number): Promise<void> {
await window.textsecure.storage.protocol.removePreKey(id);
await window.textsecure.storage.protocol.removePreKey(this.ourUuid, id);
}
}
export type SenderKeysOptions = Readonly<{
ourUuid: UUID;
}>;
export class SenderKeys extends SenderKeyStore {
private readonly ourUuid: UUID;
constructor({ ourUuid }: SenderKeysOptions) {
super();
this.ourUuid = ourUuid;
}
async saveSenderKey(
sender: ProtocolAddress,
distributionId: Uuid,
record: SenderKeyRecord
): Promise<void> {
const encodedAddress = encodedNameFromAddress(sender);
const encodedAddress = toQualifiedAddress(this.ourUuid, sender);
await window.textsecure.storage.protocol.saveSenderKey(
encodedAddress,
@ -193,7 +244,7 @@ export class SenderKeys extends SenderKeyStore {
sender: ProtocolAddress,
distributionId: Uuid
): Promise<SenderKeyRecord | null> {
const encodedAddress = encodedNameFromAddress(sender);
const encodedAddress = toQualifiedAddress(this.ourUuid, sender);
const senderKey = await window.textsecure.storage.protocol.getSenderKey(
encodedAddress,
@ -204,12 +255,24 @@ export class SenderKeys extends SenderKeyStore {
}
}
export type SignedPreKeysOptions = Readonly<{
ourUuid: UUID;
}>;
export class SignedPreKeys extends SignedPreKeyStore {
private readonly ourUuid: UUID;
constructor({ ourUuid }: SignedPreKeysOptions) {
super();
this.ourUuid = ourUuid;
}
async saveSignedPreKey(
id: number,
record: SignedPreKeyRecord
): Promise<void> {
await window.textsecure.storage.protocol.storeSignedPreKey(
this.ourUuid,
id,
freezeSignedPreKey(record),
true
@ -218,6 +281,7 @@ export class SignedPreKeys extends SignedPreKeyStore {
async getSignedPreKey(id: number): Promise<SignedPreKeyRecord> {
const signedPreKey = await window.textsecure.storage.protocol.loadSignedPreKey(
this.ourUuid,
id
);