Support for loading, storing, and using kyber keys in decryption
This commit is contained in:
parent
c1580a5eb3
commit
b6445a6af0
49 changed files with 2260 additions and 806 deletions
|
@ -52,6 +52,8 @@ import type {
|
|||
SignedPreKeyIdType,
|
||||
SignedPreKeyType,
|
||||
StoredSignedPreKeyType,
|
||||
KyberPreKeyType,
|
||||
StoredKyberPreKeyType,
|
||||
} from './Interface';
|
||||
import { MINUTE } from '../util/durations';
|
||||
import { getMessageIdForLogging } from '../util/idForLogging';
|
||||
|
@ -73,6 +75,11 @@ const exclusiveInterface: ClientExclusiveInterface = {
|
|||
bulkAddIdentityKeys,
|
||||
getAllIdentityKeys,
|
||||
|
||||
createOrUpdateKyberPreKey,
|
||||
getKyberPreKeyById,
|
||||
bulkAddKyberPreKeys,
|
||||
getAllKyberPreKeys,
|
||||
|
||||
createOrUpdatePreKey,
|
||||
getPreKeyById,
|
||||
bulkAddPreKeys,
|
||||
|
@ -248,6 +255,37 @@ async function getAllIdentityKeys(): Promise<Array<IdentityKeyType>> {
|
|||
return keys.map(key => specToBytes(IDENTITY_KEY_SPEC, key));
|
||||
}
|
||||
|
||||
// Kyber Pre Keys
|
||||
|
||||
const KYBER_PRE_KEY_SPEC = ['data'];
|
||||
async function createOrUpdateKyberPreKey(data: KyberPreKeyType): Promise<void> {
|
||||
const updated: StoredKyberPreKeyType = specFromBytes(
|
||||
KYBER_PRE_KEY_SPEC,
|
||||
data
|
||||
);
|
||||
await channels.createOrUpdateKyberPreKey(updated);
|
||||
}
|
||||
async function getKyberPreKeyById(
|
||||
id: PreKeyIdType
|
||||
): Promise<KyberPreKeyType | undefined> {
|
||||
const data = await channels.getPreKeyById(id);
|
||||
|
||||
return specToBytes(KYBER_PRE_KEY_SPEC, data);
|
||||
}
|
||||
async function bulkAddKyberPreKeys(
|
||||
array: Array<KyberPreKeyType>
|
||||
): Promise<void> {
|
||||
const updated: Array<StoredKyberPreKeyType> = map(array, data =>
|
||||
specFromBytes(KYBER_PRE_KEY_SPEC, data)
|
||||
);
|
||||
await channels.bulkAddKyberPreKeys(updated);
|
||||
}
|
||||
async function getAllKyberPreKeys(): Promise<Array<KyberPreKeyType>> {
|
||||
const keys = await channels.getAllPreKeys();
|
||||
|
||||
return keys.map(key => specToBytes(KYBER_PRE_KEY_SPEC, key));
|
||||
}
|
||||
|
||||
// Pre Keys
|
||||
|
||||
async function createOrUpdatePreKey(data: PreKeyType): Promise<void> {
|
||||
|
|
|
@ -109,21 +109,35 @@ export type MessageType = MessageAttributesType;
|
|||
export type MessageTypeUnhydrated = {
|
||||
json: string;
|
||||
};
|
||||
|
||||
export type PreKeyIdType = `${UUIDStringType}:${number}`;
|
||||
export type KyberPreKeyType = {
|
||||
id: PreKeyIdType;
|
||||
|
||||
createdAt: number;
|
||||
data: Uint8Array;
|
||||
isConfirmed: boolean;
|
||||
isLastResort: boolean;
|
||||
keyId: number;
|
||||
ourUuid: UUIDStringType;
|
||||
};
|
||||
export type StoredKyberPreKeyType = KyberPreKeyType & {
|
||||
data: string;
|
||||
};
|
||||
export type PreKeyType = {
|
||||
id: `${UUIDStringType}:${number}`;
|
||||
id: PreKeyIdType;
|
||||
|
||||
createdAt: number;
|
||||
keyId: number;
|
||||
ourUuid: UUIDStringType;
|
||||
privateKey: Uint8Array;
|
||||
publicKey: Uint8Array;
|
||||
};
|
||||
export type StoredPreKeyType = {
|
||||
id: `${UUIDStringType}:${number}`;
|
||||
keyId: number;
|
||||
ourUuid: UUIDStringType;
|
||||
|
||||
export type StoredPreKeyType = PreKeyType & {
|
||||
privateKey: string;
|
||||
publicKey: string;
|
||||
};
|
||||
export type PreKeyIdType = PreKeyType['id'];
|
||||
export type ServerSearchResultMessageType = {
|
||||
json: string;
|
||||
|
||||
|
@ -410,16 +424,24 @@ export type DataInterface = {
|
|||
removeIdentityKeyById: (id: IdentityKeyIdType) => Promise<void>;
|
||||
removeAllIdentityKeys: () => Promise<void>;
|
||||
|
||||
removePreKeyById: (id: PreKeyIdType) => Promise<void>;
|
||||
removeKyberPreKeyById: (
|
||||
id: PreKeyIdType | Array<PreKeyIdType>
|
||||
) => Promise<void>;
|
||||
removeKyberPreKeysByUuid: (uuid: UUIDStringType) => Promise<void>;
|
||||
removeAllKyberPreKeys: () => Promise<void>;
|
||||
|
||||
removePreKeyById: (id: PreKeyIdType | Array<PreKeyIdType>) => Promise<void>;
|
||||
removePreKeysByUuid: (uuid: UUIDStringType) => Promise<void>;
|
||||
removeAllPreKeys: () => Promise<void>;
|
||||
|
||||
removeSignedPreKeyById: (id: SignedPreKeyIdType) => Promise<void>;
|
||||
removeSignedPreKeyById: (
|
||||
id: SignedPreKeyIdType | Array<SignedPreKeyIdType>
|
||||
) => Promise<void>;
|
||||
removeSignedPreKeysByUuid: (uuid: UUIDStringType) => Promise<void>;
|
||||
removeAllSignedPreKeys: () => Promise<void>;
|
||||
|
||||
removeAllItems: () => Promise<void>;
|
||||
removeItemById: (id: ItemKeyType) => Promise<void>;
|
||||
removeItemById: (id: ItemKeyType | Array<ItemKeyType>) => Promise<void>;
|
||||
|
||||
createOrUpdateSenderKey: (key: SenderKeyType) => Promise<void>;
|
||||
getSenderKeyById: (id: SenderKeyIdType) => Promise<SenderKeyType | undefined>;
|
||||
|
@ -822,6 +844,13 @@ export type ServerInterface = DataInterface & {
|
|||
bulkAddIdentityKeys: (array: Array<StoredIdentityKeyType>) => Promise<void>;
|
||||
getAllIdentityKeys: () => Promise<Array<StoredIdentityKeyType>>;
|
||||
|
||||
createOrUpdateKyberPreKey: (data: StoredKyberPreKeyType) => Promise<void>;
|
||||
getKyberPreKeyById: (
|
||||
id: PreKeyIdType
|
||||
) => Promise<StoredKyberPreKeyType | undefined>;
|
||||
bulkAddKyberPreKeys: (array: Array<StoredKyberPreKeyType>) => Promise<void>;
|
||||
getAllKyberPreKeys: () => Promise<Array<StoredKyberPreKeyType>>;
|
||||
|
||||
createOrUpdatePreKey: (data: StoredPreKeyType) => Promise<void>;
|
||||
getPreKeyById: (id: PreKeyIdType) => Promise<StoredPreKeyType | undefined>;
|
||||
bulkAddPreKeys: (array: Array<StoredPreKeyType>) => Promise<void>;
|
||||
|
@ -901,6 +930,13 @@ export type ClientExclusiveInterface = {
|
|||
bulkAddIdentityKeys: (array: Array<IdentityKeyType>) => Promise<void>;
|
||||
getAllIdentityKeys: () => Promise<Array<IdentityKeyType>>;
|
||||
|
||||
createOrUpdateKyberPreKey: (data: KyberPreKeyType) => Promise<void>;
|
||||
getKyberPreKeyById: (
|
||||
id: PreKeyIdType
|
||||
) => Promise<KyberPreKeyType | undefined>;
|
||||
bulkAddKyberPreKeys: (array: Array<KyberPreKeyType>) => Promise<void>;
|
||||
getAllKyberPreKeys: () => Promise<Array<KyberPreKeyType>>;
|
||||
|
||||
createOrUpdatePreKey: (data: PreKeyType) => Promise<void>;
|
||||
getPreKeyById: (id: PreKeyIdType) => Promise<PreKeyType | undefined>;
|
||||
bulkAddPreKeys: (array: Array<PreKeyType>) => Promise<void>;
|
||||
|
|
|
@ -133,6 +133,7 @@ import type {
|
|||
UnprocessedType,
|
||||
UnprocessedUpdateType,
|
||||
GetNearbyMessageFromDeletedSetOptionsType,
|
||||
StoredKyberPreKeyType,
|
||||
} from './Interface';
|
||||
import { SeenStatus } from '../MessageSeenStatus';
|
||||
import {
|
||||
|
@ -173,6 +174,14 @@ const dataInterface: ServerInterface = {
|
|||
removeAllIdentityKeys,
|
||||
getAllIdentityKeys,
|
||||
|
||||
createOrUpdateKyberPreKey,
|
||||
getKyberPreKeyById,
|
||||
bulkAddKyberPreKeys,
|
||||
removeKyberPreKeyById,
|
||||
removeKyberPreKeysByUuid,
|
||||
removeAllKyberPreKeys,
|
||||
getAllKyberPreKeys,
|
||||
|
||||
createOrUpdatePreKey,
|
||||
getPreKeyById,
|
||||
bulkAddPreKeys,
|
||||
|
@ -655,6 +664,40 @@ async function getAllIdentityKeys(): Promise<Array<StoredIdentityKeyType>> {
|
|||
return getAllFromTable(getInstance(), IDENTITY_KEYS_TABLE);
|
||||
}
|
||||
|
||||
const KYBER_PRE_KEYS_TABLE = 'kyberPreKeys';
|
||||
async function createOrUpdateKyberPreKey(
|
||||
data: StoredKyberPreKeyType
|
||||
): Promise<void> {
|
||||
return createOrUpdate(getInstance(), KYBER_PRE_KEYS_TABLE, data);
|
||||
}
|
||||
async function getKyberPreKeyById(
|
||||
id: PreKeyIdType
|
||||
): Promise<StoredKyberPreKeyType | undefined> {
|
||||
return getById(getInstance(), KYBER_PRE_KEYS_TABLE, id);
|
||||
}
|
||||
async function bulkAddKyberPreKeys(
|
||||
array: Array<StoredKyberPreKeyType>
|
||||
): Promise<void> {
|
||||
return bulkAdd(getInstance(), KYBER_PRE_KEYS_TABLE, array);
|
||||
}
|
||||
async function removeKyberPreKeyById(
|
||||
id: PreKeyIdType | Array<PreKeyIdType>
|
||||
): Promise<void> {
|
||||
return removeById(getInstance(), KYBER_PRE_KEYS_TABLE, id);
|
||||
}
|
||||
async function removeKyberPreKeysByUuid(uuid: UUIDStringType): Promise<void> {
|
||||
const db = getInstance();
|
||||
db.prepare<Query>('DELETE FROM kyberPreKeys WHERE ourUuid IS $uuid;').run({
|
||||
uuid,
|
||||
});
|
||||
}
|
||||
async function removeAllKyberPreKeys(): Promise<void> {
|
||||
return removeAllFromTable(getInstance(), KYBER_PRE_KEYS_TABLE);
|
||||
}
|
||||
async function getAllKyberPreKeys(): Promise<Array<StoredKyberPreKeyType>> {
|
||||
return getAllFromTable(getInstance(), KYBER_PRE_KEYS_TABLE);
|
||||
}
|
||||
|
||||
const PRE_KEYS_TABLE = 'preKeys';
|
||||
async function createOrUpdatePreKey(data: StoredPreKeyType): Promise<void> {
|
||||
return createOrUpdate(getInstance(), PRE_KEYS_TABLE, data);
|
||||
|
@ -667,7 +710,9 @@ async function getPreKeyById(
|
|||
async function bulkAddPreKeys(array: Array<StoredPreKeyType>): Promise<void> {
|
||||
return bulkAdd(getInstance(), PRE_KEYS_TABLE, array);
|
||||
}
|
||||
async function removePreKeyById(id: PreKeyIdType): Promise<void> {
|
||||
async function removePreKeyById(
|
||||
id: PreKeyIdType | Array<PreKeyIdType>
|
||||
): Promise<void> {
|
||||
return removeById(getInstance(), PRE_KEYS_TABLE, id);
|
||||
}
|
||||
async function removePreKeysByUuid(uuid: UUIDStringType): Promise<void> {
|
||||
|
@ -699,7 +744,9 @@ async function bulkAddSignedPreKeys(
|
|||
): Promise<void> {
|
||||
return bulkAdd(getInstance(), SIGNED_PRE_KEYS_TABLE, array);
|
||||
}
|
||||
async function removeSignedPreKeyById(id: SignedPreKeyIdType): Promise<void> {
|
||||
async function removeSignedPreKeyById(
|
||||
id: SignedPreKeyIdType | Array<SignedPreKeyIdType>
|
||||
): Promise<void> {
|
||||
return removeById(getInstance(), SIGNED_PRE_KEYS_TABLE, id);
|
||||
}
|
||||
async function removeSignedPreKeysByUuid(uuid: UUIDStringType): Promise<void> {
|
||||
|
@ -755,7 +802,9 @@ async function getAllItems(): Promise<StoredAllItemsType> {
|
|||
|
||||
return result as unknown as StoredAllItemsType;
|
||||
}
|
||||
async function removeItemById(id: ItemKeyType): Promise<void> {
|
||||
async function removeItemById(
|
||||
id: ItemKeyType | Array<ItemKeyType>
|
||||
): Promise<void> {
|
||||
return removeById(getInstance(), ITEMS_TABLE, id);
|
||||
}
|
||||
async function removeAllItems(): Promise<void> {
|
||||
|
@ -4989,6 +5038,7 @@ async function removeAll(): Promise<void> {
|
|||
DELETE FROM identityKeys;
|
||||
DELETE FROM items;
|
||||
DELETE FROM jobs;
|
||||
DELETE FROM kyberPreKeys;
|
||||
DELETE FROM messages_fts;
|
||||
DELETE FROM messages;
|
||||
DELETE FROM preKeys;
|
||||
|
@ -5024,6 +5074,7 @@ async function removeAllConfiguration(
|
|||
`
|
||||
DELETE FROM identityKeys;
|
||||
DELETE FROM jobs;
|
||||
DELETE FROM kyberPreKeys;
|
||||
DELETE FROM preKeys;
|
||||
DELETE FROM senderKeys;
|
||||
DELETE FROM sendLogMessageIds;
|
||||
|
|
42
ts/sql/migrations/85-add-kyber-keys.ts
Normal file
42
ts/sql/migrations/85-add-kyber-keys.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2023 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { Database } from '@signalapp/better-sqlite3';
|
||||
|
||||
import type { LoggerType } from '../../types/Logging';
|
||||
|
||||
export default function updateToSchemaVersion85(
|
||||
currentVersion: number,
|
||||
db: Database,
|
||||
logger: LoggerType
|
||||
): void {
|
||||
if (currentVersion >= 85) {
|
||||
return;
|
||||
}
|
||||
|
||||
db.transaction(() => {
|
||||
db.exec(
|
||||
`CREATE TABLE kyberPreKeys(
|
||||
id STRING PRIMARY KEY NOT NULL,
|
||||
json TEXT NOT NULL,
|
||||
ourUuid STRING
|
||||
GENERATED ALWAYS AS (json_extract(json, '$.ourUuid'))
|
||||
);`
|
||||
);
|
||||
|
||||
// To manage our ACI or PNI keys quickly
|
||||
db.exec('CREATE INDEX kyberPreKeys_ourUuid ON kyberPreKeys (ourUuid);');
|
||||
|
||||
// Add time to all existing preKeys to allow us to expire them
|
||||
const now = Date.now();
|
||||
db.exec(
|
||||
`UPDATE preKeys SET
|
||||
json = json_set(json, '$.createdAt', ${now});
|
||||
`
|
||||
);
|
||||
|
||||
db.pragma('user_version = 85');
|
||||
})();
|
||||
|
||||
logger.info('updateToSchemaVersion85: success!');
|
||||
}
|
|
@ -60,6 +60,7 @@ import updateToSchemaVersion81 from './81-contact-removed-notification';
|
|||
import updateToSchemaVersion82 from './82-edited-messages-read-index';
|
||||
import updateToSchemaVersion83 from './83-mentions';
|
||||
import updateToSchemaVersion84 from './84-all-mentions';
|
||||
import updateToSchemaVersion85 from './85-add-kyber-keys';
|
||||
|
||||
function updateToSchemaVersion1(
|
||||
currentVersion: number,
|
||||
|
@ -1984,11 +1985,13 @@ export const SCHEMA_VERSIONS = [
|
|||
updateToSchemaVersion77,
|
||||
updateToSchemaVersion78,
|
||||
updateToSchemaVersion79,
|
||||
|
||||
updateToSchemaVersion80,
|
||||
updateToSchemaVersion81,
|
||||
updateToSchemaVersion82,
|
||||
updateToSchemaVersion83,
|
||||
updateToSchemaVersion84,
|
||||
updateToSchemaVersion85,
|
||||
];
|
||||
|
||||
export function updateSchema(db: Database, logger: LoggerType): void {
|
||||
|
|
|
@ -16,6 +16,7 @@ export type TableType =
|
|||
| 'conversations'
|
||||
| 'identityKeys'
|
||||
| 'items'
|
||||
| 'kyberPreKeys'
|
||||
| 'messages'
|
||||
| 'preKeys'
|
||||
| 'senderKeys'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue