UUID-keyed lookups in SignalProtocolStore
This commit is contained in:
parent
6323aedd9b
commit
c7e7d55af4
46 changed files with 2094 additions and 1447 deletions
|
@ -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
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue