You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/session/medium_group/senderKeys.ts

108 lines
2.4 KiB
TypeScript

import { PubKey } from '../types';
import { StringUtils } from '../utils';
import * as Data from '../../../js/modules/data';
import { MediumGroupResponseKeysMessage } from '../messages/outgoing';
import { getMessageQueue } from '..';
const toHex = (buffer: ArrayBuffer) => StringUtils.decode(buffer, 'hex');
const fromHex = (hex: string) => StringUtils.encode(hex, 'hex');
export interface RatchetState {
chainKey: Uint8Array;
keyIdx: number;
pubKey: Uint8Array;
}
// TODO: make this private when no longer needed by JS
export async function saveSenderKeysInner(
groupId: string,
senderIdentity: PubKey,
chainKeyHex: string,
keyIdx: number,
messageKeys: any
) {
const { log } = window;
const ratchet = {
chainKeyHex,
messageKeys,
idx: keyIdx,
};
log.debug(
'saving ratchet keys for group ',
groupId,
'sender',
senderIdentity.key
);
await Data.createOrUpdateSenderKeys({
groupId,
senderIdentity: senderIdentity.key,
ratchet,
});
log.debug(
`Saving sender keys for groupId ${groupId}, sender ${senderIdentity.key}`
);
}
export async function createSenderKeyForGroup(
groupId: string,
senderIdentity: PubKey
): Promise<RatchetState> {
// Generate Chain Key (32 random bytes)
const rootChainKey = await window.libsignal.crypto.getRandomBytes(32);
const rootChainKeyHex = toHex(rootChainKey);
const keyIdx = 0;
const messageKeys = {};
await saveSenderKeysInner(
groupId,
senderIdentity,
rootChainKeyHex,
keyIdx,
messageKeys
);
const pubKey = new Uint8Array(fromHex(senderIdentity.key));
const chainKey = new Uint8Array(rootChainKey);
return { pubKey, chainKey, keyIdx: 0 };
}
// Save somebody else's key
export async function saveSenderKeys(
groupId: string,
senderIdentity: PubKey,
chainKeyHex: string,
keyIdx: number
) {
const messageKeys = {};
await saveSenderKeysInner(
groupId,
senderIdentity,
chainKeyHex,
keyIdx,
messageKeys
);
}
export async function shareSenderKeys(
groupId: string,
recipientsPrimary: Array<string>,
senderKey: RatchetState
) {
const message = new MediumGroupResponseKeysMessage({
timestamp: Date.now(),
groupId,
senderKey,
});
const recipients = recipientsPrimary.map(pk => PubKey.cast(pk));
await Promise.all(
recipients.map(pk => getMessageQueue().sendUsingMultiDevice(pk, message))
);
}