signal-desktop/ts/services/backups/crypto.ts

128 lines
3.6 KiB
TypeScript
Raw Normal View History

2024-04-22 14:11:36 +00:00
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import memoizee from 'memoizee';
2024-10-31 17:01:03 +00:00
import type { PrivateKey } from '@signalapp/libsignal-client';
import {
AccountEntropyPool,
BackupKey,
} from '@signalapp/libsignal-client/dist/AccountKeys';
import { MessageBackupKey } from '@signalapp/libsignal-client/dist/MessageBackup';
2024-04-22 14:11:36 +00:00
import { strictAssert } from '../../util/assert';
import type { AciString } from '../../types/ServiceId';
import { toAciObject } from '../../util/ServiceId';
2024-10-31 17:01:03 +00:00
const getMemoizedBackupKey = memoizee((accountEntropyPool: string) => {
return AccountEntropyPool.deriveBackupKey(accountEntropyPool);
2024-04-22 14:11:36 +00:00
});
2024-10-31 17:01:03 +00:00
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');
2024-04-22 14:11:36 +00:00
2024-10-31 17:01:03 +00:00
return new BackupKey(Buffer.from(rootKey));
2024-04-22 14:11:36 +00:00
}
const getMemoizedBackupSignatureKey = memoizee(
2024-10-31 17:01:03 +00:00
(backupKey: BackupKey, aci: AciString) => {
return backupKey.deriveEcKey(toAciObject(aci));
2024-04-22 14:11:36 +00:00
}
);
2024-10-31 17:01:03 +00:00
export function getBackupSignatureKey(): PrivateKey {
2024-04-22 14:11:36 +00:00
const backupKey = getBackupKey();
const aci = window.storage.user.getCheckedAci();
return getMemoizedBackupSignatureKey(backupKey, aci);
}
2024-10-31 17:01:03 +00:00
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);
}
2024-04-22 14:11:36 +00:00
const getMemoizedKeyMaterial = memoizee(
2024-10-31 17:01:03 +00:00
(backupKey: BackupKey, aci: AciString) => {
const messageKey = new MessageBackupKey({
backupKey,
backupId: backupKey.deriveBackupId(toAciObject(aci)),
});
return { macKey: messageKey.hmacKey, aesKey: messageKey.aesKey };
2024-04-22 14:11:36 +00:00
}
);
2024-10-31 17:01:03 +00:00
export type BackupKeyMaterialType = Readonly<{
macKey: Uint8Array;
aesKey: Uint8Array;
}>;
2024-10-18 17:15:03 +00:00
export function getKeyMaterial(
backupKey = getBackupKey()
): BackupKeyMaterialType {
2024-04-22 14:11:36 +00:00
const aci = window.storage.user.getCheckedAci();
return getMemoizedKeyMaterial(backupKey, aci);
}
2024-10-31 17:01:03 +00:00
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
),
};
}