snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
198
apps/meteor/client/lib/e2ee/crypto/shared.ts
Normal file
198
apps/meteor/client/lib/e2ee/crypto/shared.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
const { subtle } = crypto;
|
||||
export const randomUUID = () => crypto.randomUUID();
|
||||
export const getRandomValues = crypto.getRandomValues.bind(crypto);
|
||||
|
||||
interface IAesGcmParams extends AesGcmParams {
|
||||
name: 'AES-GCM';
|
||||
}
|
||||
|
||||
interface IAesCbcParams extends AesCbcParams {
|
||||
name: 'AES-CBC';
|
||||
}
|
||||
|
||||
interface IAesCtrParams extends AesCtrParams {
|
||||
name: 'AES-CTR';
|
||||
}
|
||||
|
||||
interface IRsaOaepParams extends RsaOaepParams {
|
||||
name: 'RSA-OAEP';
|
||||
}
|
||||
|
||||
type ParamsMap = {
|
||||
'AES-GCM': IAesGcmParams;
|
||||
'AES-CTR': IAesCtrParams;
|
||||
'AES-CBC': IAesCbcParams;
|
||||
'RSA-OAEP': IRsaOaepParams;
|
||||
};
|
||||
|
||||
type ParamsOf<TKey extends IKey> = TKey['algorithm'] extends { name: infer TName extends keyof ParamsMap } ? ParamsMap[TName] : never;
|
||||
type HasUsage<TKey extends IKey, TUsage extends KeyUsage> = TUsage extends TKey['usages'][number]
|
||||
? TKey
|
||||
: TKey & `The provided key cannot be used for ${TUsage}`;
|
||||
|
||||
export const encryptBuffer = <TKey extends IKey, TParams extends ParamsOf<TKey>>(
|
||||
key: HasUsage<TKey, 'encrypt'>,
|
||||
params: TParams,
|
||||
data: BufferSource,
|
||||
): Promise<ArrayBuffer> => subtle.encrypt(params, key, data);
|
||||
export const decryptBuffer = <TKey extends IKey>(
|
||||
key: HasUsage<TKey, 'decrypt'>,
|
||||
params: ParamsOf<TKey>,
|
||||
data: BufferSource,
|
||||
): Promise<ArrayBuffer> => subtle.decrypt(params, key, data);
|
||||
export const deriveBits = (...args: Parameters<typeof subtle.deriveBits>) => subtle.deriveBits(...args);
|
||||
|
||||
type AesParams = {
|
||||
name: 'AES-CBC' | 'AES-GCM' | 'AES-CTR';
|
||||
length: 128 | 256;
|
||||
};
|
||||
|
||||
type ModeOf<T extends `AES-${'CBC' | 'GCM' | 'CTR'}`> = T extends `AES-${infer Mode}` ? Mode : never;
|
||||
|
||||
type Permutations<T> = T extends [infer First]
|
||||
? [First]
|
||||
: T extends [infer First, infer Second]
|
||||
? [First, Second] | [Second, First]
|
||||
: never;
|
||||
|
||||
export interface IKey<
|
||||
TAlgorithm extends CryptoKey['algorithm'] = CryptoKey['algorithm'],
|
||||
TExtractable extends CryptoKey['extractable'] = CryptoKey['extractable'],
|
||||
TType extends CryptoKey['type'] = CryptoKey['type'],
|
||||
TUsages extends CryptoKey['usages'] = CryptoKey['usages'],
|
||||
> extends CryptoKey {
|
||||
readonly algorithm: TAlgorithm;
|
||||
readonly extractable: TExtractable;
|
||||
readonly type: TType;
|
||||
readonly usages: Permutations<TUsages>;
|
||||
}
|
||||
|
||||
export async function generateKey<
|
||||
const T extends AesParams,
|
||||
const TExtractable extends boolean = boolean,
|
||||
const TUsages extends KeyUsage[] = KeyUsage[],
|
||||
>(algorithm: T, extractable: TExtractable, keyUsages: TUsages): Promise<IKey<T, TExtractable, 'secret', TUsages>> {
|
||||
const key = await subtle.generateKey(algorithm, extractable, keyUsages);
|
||||
return key as IKey<T, TExtractable, 'secret', TUsages>;
|
||||
}
|
||||
|
||||
type Filter<TItem extends KeyUsage, TArray extends KeyUsage[], Out extends KeyUsage[] = []> = TArray extends [
|
||||
infer First extends KeyUsage,
|
||||
...infer Rest extends KeyUsage[],
|
||||
]
|
||||
? First extends TItem
|
||||
? Filter<TItem, Rest, [...Out, First]>
|
||||
: Filter<TItem, Rest, Out>
|
||||
: Out;
|
||||
|
||||
export interface IKeyPair<
|
||||
T extends KeyAlgorithm = KeyAlgorithm,
|
||||
TExtractable extends boolean = boolean,
|
||||
TUsages extends KeyUsage[] = KeyUsage[],
|
||||
> extends CryptoKeyPair {
|
||||
publicKey: IKey<T, TExtractable, 'public', Filter<'encrypt', TUsages>>;
|
||||
privateKey: IKey<T, TExtractable, 'private', Filter<'decrypt', TUsages>>;
|
||||
}
|
||||
|
||||
type RsaParams = {
|
||||
name: 'RSA-OAEP';
|
||||
modulusLength: 2048;
|
||||
publicExponent: Uint8Array<ArrayBuffer>;
|
||||
hash: { name: 'SHA-256' };
|
||||
};
|
||||
|
||||
export async function generateKeyPair<
|
||||
const T extends RsaParams,
|
||||
const TExtractable extends boolean = boolean,
|
||||
const TUsages extends KeyUsage[] = KeyUsage[],
|
||||
>(algorithm: T, extractable: TExtractable, keyUsages: TUsages): Promise<IKeyPair<T, TExtractable, TUsages>> {
|
||||
const keyPair = await subtle.generateKey(algorithm, extractable, keyUsages);
|
||||
return keyPair as IKeyPair<T, TExtractable, TUsages>;
|
||||
}
|
||||
|
||||
type KeyToJwk<T extends IKey> = T['extractable'] extends false
|
||||
? never
|
||||
: T['algorithm'] extends AesParams
|
||||
? {
|
||||
kty: 'oct';
|
||||
alg: `A${T['algorithm']['length']}${ModeOf<T['algorithm']['name']>}`;
|
||||
ext: true;
|
||||
k: string;
|
||||
key_ops: T['usages'];
|
||||
}
|
||||
: [T['algorithm'], T['type']] extends [RsaParams, 'public']
|
||||
? {
|
||||
kty: 'RSA';
|
||||
alg: 'RSA-OAEP-256';
|
||||
e: string;
|
||||
ext: true;
|
||||
key_ops: T['usages'];
|
||||
n: string;
|
||||
}
|
||||
: [T['algorithm'], T['type']] extends [RsaParams, 'private']
|
||||
? {
|
||||
kty: 'RSA';
|
||||
alg: 'RSA-OAEP-256';
|
||||
e: string;
|
||||
ext: true;
|
||||
d: string;
|
||||
dp: string;
|
||||
dq: string;
|
||||
key_ops: T['usages'];
|
||||
n: string;
|
||||
p: string;
|
||||
q: string;
|
||||
qi: string;
|
||||
}
|
||||
: never;
|
||||
|
||||
export type Exported<TFormat extends KeyFormat, TKey extends IKey = IKey> = TFormat extends 'jwk' ? KeyToJwk<TKey> : ArrayBuffer;
|
||||
|
||||
export async function exportKey<const TFormat extends KeyFormat = KeyFormat, const TKey extends IKey = IKey>(
|
||||
format: TFormat,
|
||||
key: TKey,
|
||||
): Promise<Exported<TFormat, TKey>> {
|
||||
const exportedKey = await subtle.exportKey(format, key);
|
||||
return exportedKey as Exported<TFormat, TKey>;
|
||||
}
|
||||
|
||||
type KtyParams = {
|
||||
oct: AesParams;
|
||||
RSA: RsaParams;
|
||||
};
|
||||
|
||||
export async function importJwk<
|
||||
const TKeyData extends JsonWebKey,
|
||||
const TAlgorithm extends (TKeyData extends { kty: infer Kty extends keyof KtyParams } ? KtyParams[Kty] : KeyAlgorithm),
|
||||
const TExtractable extends boolean = boolean,
|
||||
const TUsages extends KeyUsage[] = KeyUsage[],
|
||||
const TKeyType extends KeyType = TKeyData extends { kty: 'oct' }
|
||||
? 'secret'
|
||||
: TKeyData extends { kty: 'RSA'; key_ops: [infer Op] }
|
||||
? Op extends 'encrypt'
|
||||
? 'public'
|
||||
: 'private'
|
||||
: KeyType,
|
||||
>(
|
||||
jwk: TKeyData,
|
||||
algorithm: TAlgorithm,
|
||||
extractable: TExtractable,
|
||||
keyUsages: TUsages,
|
||||
): Promise<IKey<TAlgorithm, TExtractable, TKeyType, TUsages>> {
|
||||
const key = await subtle.importKey('jwk', jwk, algorithm, extractable, keyUsages);
|
||||
return key as IKey<TAlgorithm, TExtractable, TKeyType, TUsages>;
|
||||
}
|
||||
|
||||
export async function importRaw<
|
||||
const TAlgorithm extends KeyAlgorithm = KeyAlgorithm,
|
||||
const TExtractable extends boolean = boolean,
|
||||
const TUsages extends KeyUsage[] = KeyUsage[],
|
||||
>(
|
||||
rawKey: BufferSource,
|
||||
algorithm: TAlgorithm,
|
||||
extractable: TExtractable,
|
||||
keyUsages: TUsages,
|
||||
): Promise<IKey<TAlgorithm, TExtractable, 'secret', TUsages>> {
|
||||
const key = await subtle.importKey('raw', rawKey, algorithm, extractable, keyUsages);
|
||||
return key as IKey<TAlgorithm, TExtractable, 'secret', TUsages>;
|
||||
}
|
||||
Reference in New Issue
Block a user