4dde3df4d3
Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com>
127 lines
3.6 KiB
TypeScript
127 lines
3.6 KiB
TypeScript
// Copyright 2024 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import memoizee from 'memoizee';
|
|
import type { PrivateKey } from '@signalapp/libsignal-client';
|
|
import {
|
|
AccountEntropyPool,
|
|
BackupKey,
|
|
} from '@signalapp/libsignal-client/dist/AccountKeys';
|
|
import { MessageBackupKey } from '@signalapp/libsignal-client/dist/MessageBackup';
|
|
|
|
import { strictAssert } from '../../util/assert';
|
|
import type { AciString } from '../../types/ServiceId';
|
|
import { toAciObject } from '../../util/ServiceId';
|
|
|
|
const getMemoizedBackupKey = memoizee((accountEntropyPool: string) => {
|
|
return AccountEntropyPool.deriveBackupKey(accountEntropyPool);
|
|
});
|
|
|
|
export function getBackupKey(): BackupKey {
|
|
const accountEntropyPool = window.storage.get('accountEntropyPool');
|
|
strictAssert(accountEntropyPool, 'Account Entropy Pool not available');
|
|
|
|
return getMemoizedBackupKey(accountEntropyPool);
|
|
}
|
|
|
|
export function getBackupMediaRootKey(): BackupKey {
|
|
const rootKey = window.storage.get('backupMediaRootKey');
|
|
strictAssert(rootKey, 'Media root key not available');
|
|
|
|
return new BackupKey(Buffer.from(rootKey));
|
|
}
|
|
|
|
const getMemoizedBackupSignatureKey = memoizee(
|
|
(backupKey: BackupKey, aci: AciString) => {
|
|
return backupKey.deriveEcKey(toAciObject(aci));
|
|
}
|
|
);
|
|
|
|
export function getBackupSignatureKey(): PrivateKey {
|
|
const backupKey = getBackupKey();
|
|
const aci = window.storage.user.getCheckedAci();
|
|
return getMemoizedBackupSignatureKey(backupKey, aci);
|
|
}
|
|
|
|
const getMemoizedBackupMediaSignatureKey = memoizee(
|
|
(rootKey: BackupKey, aci: AciString) => {
|
|
return rootKey.deriveEcKey(toAciObject(aci));
|
|
}
|
|
);
|
|
|
|
export function getBackupMediaSignatureKey(): PrivateKey {
|
|
const rootKey = getBackupMediaRootKey();
|
|
const aci = window.storage.user.getCheckedAci();
|
|
return getMemoizedBackupMediaSignatureKey(rootKey, aci);
|
|
}
|
|
|
|
const getMemoizedKeyMaterial = memoizee(
|
|
(backupKey: BackupKey, aci: AciString) => {
|
|
const messageKey = new MessageBackupKey({
|
|
backupKey,
|
|
backupId: backupKey.deriveBackupId(toAciObject(aci)),
|
|
});
|
|
|
|
return { macKey: messageKey.hmacKey, aesKey: messageKey.aesKey };
|
|
}
|
|
);
|
|
|
|
export type BackupKeyMaterialType = Readonly<{
|
|
macKey: Uint8Array;
|
|
aesKey: Uint8Array;
|
|
}>;
|
|
|
|
export function getKeyMaterial(
|
|
backupKey = getBackupKey()
|
|
): BackupKeyMaterialType {
|
|
const aci = window.storage.user.getCheckedAci();
|
|
return getMemoizedKeyMaterial(backupKey, aci);
|
|
}
|
|
|
|
export type BackupMediaKeyMaterialType = Readonly<{
|
|
macKey: Uint8Array;
|
|
aesKey: Uint8Array;
|
|
}>;
|
|
|
|
const BACKUP_MEDIA_AES_KEY_LEN = 32;
|
|
const BACKUP_MEDIA_MAC_KEY_LEN = 32;
|
|
|
|
export function deriveBackupMediaKeyMaterial(
|
|
mediaRootKey: BackupKey,
|
|
mediaId: Uint8Array
|
|
): BackupMediaKeyMaterialType {
|
|
if (!mediaId.length) {
|
|
throw new Error('deriveBackupMediaKeyMaterial: mediaId missing');
|
|
}
|
|
|
|
const material = mediaRootKey.deriveMediaEncryptionKey(Buffer.from(mediaId));
|
|
|
|
return {
|
|
macKey: material.subarray(0, BACKUP_MEDIA_MAC_KEY_LEN),
|
|
aesKey: material.subarray(
|
|
BACKUP_MEDIA_MAC_KEY_LEN,
|
|
BACKUP_MEDIA_MAC_KEY_LEN + BACKUP_MEDIA_AES_KEY_LEN
|
|
),
|
|
};
|
|
}
|
|
|
|
export function deriveBackupThumbnailTransitKeyMaterial(
|
|
mediaRootKey: BackupKey,
|
|
mediaId: Uint8Array
|
|
): BackupMediaKeyMaterialType {
|
|
if (!mediaId.length) {
|
|
throw new Error('deriveBackupThumbnailTransitKeyMaterial: mediaId missing');
|
|
}
|
|
|
|
const material = mediaRootKey.deriveThumbnailTransitEncryptionKey(
|
|
Buffer.from(mediaId)
|
|
);
|
|
|
|
return {
|
|
macKey: material.subarray(0, BACKUP_MEDIA_MAC_KEY_LEN),
|
|
aesKey: material.subarray(
|
|
BACKUP_MEDIA_MAC_KEY_LEN,
|
|
BACKUP_MEDIA_MAC_KEY_LEN + BACKUP_MEDIA_AES_KEY_LEN
|
|
),
|
|
};
|
|
}
|