signal-desktop/ts/util/encryptProfileData.ts

86 lines
2.5 KiB
TypeScript
Raw Normal View History

2021-07-19 19:26:06 +00:00
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { ConversationType } from '../state/ducks/conversations';
import type { ProfileRequestDataType } from '../textsecure/WebAPI';
import { assertDev } from './assert';
2021-09-24 00:49:05 +00:00
import * as Bytes from '../Bytes';
2021-07-19 19:26:06 +00:00
import {
2021-09-24 00:49:05 +00:00
PaddedLengths,
encryptProfile,
encryptProfileItemWithPadding,
2021-07-19 19:26:06 +00:00
} from '../Crypto';
import type { AvatarUpdateType } from '../types/Avatar';
2021-07-19 19:26:06 +00:00
import { deriveProfileKeyCommitment, deriveProfileKeyVersion } from './zkgroup';
import { isSharingPhoneNumberWithEverybody } from './phoneNumberSharingMode';
2021-07-19 19:26:06 +00:00
export async function encryptProfileData(
conversation: ConversationType,
{ oldAvatar, newAvatar }: AvatarUpdateType
2021-09-24 00:49:05 +00:00
): Promise<[ProfileRequestDataType, Uint8Array | undefined]> {
const {
aboutEmoji,
aboutText,
badges,
familyName,
firstName,
profileKey,
2023-08-16 20:54:39 +00:00
serviceId,
} = conversation;
2021-07-19 19:26:06 +00:00
assertDev(profileKey, 'profileKey');
2023-08-16 20:54:39 +00:00
assertDev(serviceId, 'serviceId');
2021-07-19 19:26:06 +00:00
2021-09-24 00:49:05 +00:00
const keyBuffer = Bytes.fromBase64(profileKey);
2021-07-19 19:26:06 +00:00
const fullName = [firstName, familyName].filter(Boolean).join('\0');
2021-09-24 00:49:05 +00:00
const bytesName = encryptProfileItemWithPadding(
Bytes.fromString(fullName),
keyBuffer,
PaddedLengths.Name
);
const bytesAbout = aboutText
? encryptProfileItemWithPadding(
Bytes.fromString(aboutText),
keyBuffer,
PaddedLengths.About
)
: null;
const bytesAboutEmoji = aboutEmoji
? encryptProfileItemWithPadding(
Bytes.fromString(aboutEmoji),
keyBuffer,
PaddedLengths.AboutEmoji
)
: null;
const encryptedPhoneNumberSharing = encryptProfile(
new Uint8Array([isSharingPhoneNumberWithEverybody() ? 1 : 0]),
keyBuffer
);
const encryptedAvatarData = newAvatar
? encryptProfile(newAvatar, keyBuffer)
2021-09-24 00:49:05 +00:00
: undefined;
2021-07-19 19:26:06 +00:00
const sameAvatar = Bytes.areEqual(oldAvatar, newAvatar);
2021-07-19 19:26:06 +00:00
const profileData = {
2023-08-16 20:54:39 +00:00
version: deriveProfileKeyVersion(profileKey, serviceId),
2021-09-24 00:49:05 +00:00
name: Bytes.toBase64(bytesName),
about: bytesAbout ? Bytes.toBase64(bytesAbout) : null,
aboutEmoji: bytesAboutEmoji ? Bytes.toBase64(bytesAboutEmoji) : null,
badgeIds: (badges || []).map(({ id }) => id),
2021-07-19 19:26:06 +00:00
paymentAddress: window.storage.get('paymentAddress') || null,
avatar: Boolean(newAvatar),
sameAvatar,
2023-08-16 20:54:39 +00:00
commitment: deriveProfileKeyCommitment(profileKey, serviceId),
phoneNumberSharing: Bytes.toBase64(encryptedPhoneNumberSharing),
2021-07-19 19:26:06 +00:00
};
return [profileData, encryptedAvatarData];
}