2020-10-30 20:34:04 +00:00
|
|
|
// Copyright 2020 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2022-03-24 21:47:21 +00:00
|
|
|
import { PublicKey, Fingerprint } from '@signalapp/libsignal-client';
|
2021-10-26 19:15:33 +00:00
|
|
|
import type { ConversationType } from '../state/ducks/conversations';
|
2021-09-10 02:38:11 +00:00
|
|
|
import { UUID } from '../types/UUID';
|
2020-06-26 00:08:58 +00:00
|
|
|
|
2022-09-15 19:17:15 +00:00
|
|
|
import { assertDev } from './assert';
|
2023-04-07 17:46:00 +00:00
|
|
|
import { missingCaseError } from './missingCaseError';
|
2021-09-17 18:27:53 +00:00
|
|
|
import * as log from '../logging/log';
|
2021-06-15 00:09:37 +00:00
|
|
|
|
2023-04-07 17:46:00 +00:00
|
|
|
function generateSecurityNumber(
|
|
|
|
ourId: string,
|
2021-09-24 00:49:05 +00:00
|
|
|
ourKey: Uint8Array,
|
2023-04-07 17:46:00 +00:00
|
|
|
theirId: string,
|
2021-09-24 00:49:05 +00:00
|
|
|
theirKey: Uint8Array
|
2023-04-07 17:46:00 +00:00
|
|
|
): string {
|
|
|
|
const ourNumberBuf = Buffer.from(ourId);
|
2021-02-23 23:34:23 +00:00
|
|
|
const ourKeyObj = PublicKey.deserialize(Buffer.from(ourKey));
|
2023-04-07 17:46:00 +00:00
|
|
|
const theirNumberBuf = Buffer.from(theirId);
|
2021-02-23 23:34:23 +00:00
|
|
|
const theirKeyObj = PublicKey.deserialize(Buffer.from(theirKey));
|
|
|
|
|
|
|
|
const fingerprint = Fingerprint.new(
|
|
|
|
5200,
|
|
|
|
2,
|
|
|
|
ourNumberBuf,
|
|
|
|
ourKeyObj,
|
|
|
|
theirNumberBuf,
|
|
|
|
theirKeyObj
|
2020-06-26 00:08:58 +00:00
|
|
|
);
|
2021-02-23 23:34:23 +00:00
|
|
|
|
2023-04-07 17:46:00 +00:00
|
|
|
return fingerprint.displayableFingerprint().toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
export enum SecurityNumberIdentifierType {
|
|
|
|
UUIDIdentifier = 'UUIDIdentifier',
|
|
|
|
E164Identifier = 'E164Identifier',
|
2020-06-26 00:08:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export async function generateSecurityNumberBlock(
|
2023-04-07 17:46:00 +00:00
|
|
|
contact: ConversationType,
|
|
|
|
identifierType: SecurityNumberIdentifierType
|
2020-06-26 00:08:58 +00:00
|
|
|
): Promise<Array<string>> {
|
2023-04-07 17:46:00 +00:00
|
|
|
const logId = `generateSecurityNumberBlock(${contact.id}, ${identifierType})`;
|
|
|
|
log.info(`${logId}: starting`);
|
|
|
|
|
2021-09-10 02:38:11 +00:00
|
|
|
const { storage } = window.textsecure;
|
|
|
|
const ourNumber = storage.user.getNumber();
|
|
|
|
const ourUuid = storage.user.getCheckedUuid();
|
2020-06-26 00:08:58 +00:00
|
|
|
|
2021-09-10 02:38:11 +00:00
|
|
|
const us = storage.protocol.getIdentityRecord(ourUuid);
|
2020-06-26 00:08:58 +00:00
|
|
|
const ourKey = us ? us.publicKey : null;
|
|
|
|
|
2021-09-10 02:38:11 +00:00
|
|
|
const theirUuid = UUID.lookup(contact.id);
|
|
|
|
const them = theirUuid
|
|
|
|
? await storage.protocol.getOrMigrateIdentityRecord(theirUuid)
|
|
|
|
: undefined;
|
|
|
|
const theirKey = them?.publicKey;
|
2020-06-26 00:08:58 +00:00
|
|
|
|
|
|
|
if (!ourKey) {
|
|
|
|
throw new Error('Could not load our key');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!theirKey) {
|
|
|
|
throw new Error('Could not load their key');
|
|
|
|
}
|
|
|
|
|
2023-04-07 17:46:00 +00:00
|
|
|
let securityNumber: string;
|
|
|
|
if (identifierType === SecurityNumberIdentifierType.E164Identifier) {
|
|
|
|
if (!contact.e164) {
|
|
|
|
log.error(
|
|
|
|
`${logId}: Attempted to generate security number for contact with no e164`
|
|
|
|
);
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
assertDev(ourNumber, 'Should have our number');
|
|
|
|
securityNumber = generateSecurityNumber(
|
|
|
|
ourNumber,
|
|
|
|
ourKey,
|
|
|
|
contact.e164,
|
|
|
|
theirKey
|
2020-07-24 01:35:32 +00:00
|
|
|
);
|
2023-04-07 17:46:00 +00:00
|
|
|
} else if (identifierType === SecurityNumberIdentifierType.UUIDIdentifier) {
|
|
|
|
assertDev(theirUuid, 'Should have their uuid');
|
|
|
|
securityNumber = generateSecurityNumber(
|
|
|
|
ourUuid.toString(),
|
|
|
|
ourKey,
|
|
|
|
theirUuid.toString(),
|
|
|
|
theirKey
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
throw missingCaseError(identifierType);
|
2020-07-24 01:35:32 +00:00
|
|
|
}
|
|
|
|
|
2020-06-26 00:08:58 +00:00
|
|
|
const chunks = [];
|
|
|
|
for (let i = 0; i < securityNumber.length; i += 5) {
|
|
|
|
chunks.push(securityNumber.substring(i, i + 5));
|
|
|
|
}
|
|
|
|
|
|
|
|
return chunks;
|
|
|
|
}
|