mirror of
https://github.com/bitwarden/browser.git
synced 2025-04-06 18:47:05 +02:00
add org key type and new method to build a data enc key for orgs
This commit is contained in:
parent
2789fdc393
commit
8353d67e1f
@ -7,6 +7,7 @@ import { EncArrayBuffer } from "../models/domain/enc-array-buffer";
|
||||
import { EncString } from "../models/domain/enc-string";
|
||||
import {
|
||||
MasterKey,
|
||||
OrgKey,
|
||||
PinKey,
|
||||
SymmetricCryptoKey,
|
||||
UserSymKey,
|
||||
@ -188,11 +189,16 @@ export abstract class CryptoService {
|
||||
* @param orgId The desired organization
|
||||
* @returns The organization's symmetric key
|
||||
*/
|
||||
getOrgKey: (orgId: string) => Promise<SymmetricCryptoKey>;
|
||||
getOrgKey: (orgId: string) => Promise<OrgKey>;
|
||||
/**
|
||||
* @returns A map of the organization Ids to their symmetric keys
|
||||
*/
|
||||
getOrgKeys: () => Promise<Map<string, SymmetricCryptoKey>>;
|
||||
/**
|
||||
* Uses the org key to derive a new symmetric key for encrypting data
|
||||
* @param orgKey The organization's symmetric key
|
||||
*/
|
||||
makeOrgDataEncKey: (orgKey: OrgKey) => Promise<[SymmetricCryptoKey, EncString]>;
|
||||
/**
|
||||
* Clears the user's stored organization keys
|
||||
* @param memoryOnly Clear only the in-memory keys
|
||||
|
@ -81,3 +81,4 @@ export type DeviceKey = Opaque<SymmetricCryptoKey, "DeviceKey">;
|
||||
export type UserSymKey = Opaque<SymmetricCryptoKey, "UserSymKey">;
|
||||
export type MasterKey = Opaque<SymmetricCryptoKey, "MasterKey">;
|
||||
export type PinKey = Opaque<SymmetricCryptoKey, "PinKey">;
|
||||
export type OrgKey = Opaque<SymmetricCryptoKey, "OrgKey">;
|
||||
|
@ -28,6 +28,7 @@ import { EncArrayBuffer } from "../models/domain/enc-array-buffer";
|
||||
import { EncString } from "../models/domain/enc-string";
|
||||
import {
|
||||
MasterKey,
|
||||
OrgKey,
|
||||
PinKey,
|
||||
SymmetricCryptoKey,
|
||||
UserSymKey,
|
||||
@ -114,7 +115,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
}
|
||||
|
||||
const newUserSymKey = await this.cryptoFunctionService.randomBytes(64);
|
||||
return this.buildProtectedUserSymKey(masterKey, newUserSymKey);
|
||||
return this.buildProtectedSymmetricKey(masterKey, newUserSymKey);
|
||||
}
|
||||
|
||||
async clearUserKey(clearStoredKeys = true, userId?: string): Promise<void> {
|
||||
@ -155,7 +156,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
userSymKey?: UserSymKey
|
||||
): Promise<[UserSymKey, EncString]> {
|
||||
userSymKey ||= await this.getUserKeyFromMemory();
|
||||
return this.buildProtectedUserSymKey(masterKey, userSymKey.key);
|
||||
return this.buildProtectedSymmetricKey(masterKey, userSymKey.key);
|
||||
}
|
||||
|
||||
async decryptUserSymKeyWithMasterKey(
|
||||
@ -271,7 +272,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return await this.stateService.setEncryptedOrganizationKeys(encOrgKeyData);
|
||||
}
|
||||
|
||||
async getOrgKey(orgId: string): Promise<SymmetricCryptoKey> {
|
||||
async getOrgKey(orgId: string): Promise<OrgKey> {
|
||||
if (orgId == null) {
|
||||
return null;
|
||||
}
|
||||
@ -285,11 +286,11 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
}
|
||||
|
||||
@sequentialize(() => "getOrgKeys")
|
||||
async getOrgKeys(): Promise<Map<string, SymmetricCryptoKey>> {
|
||||
const result: Map<string, SymmetricCryptoKey> = new Map<string, SymmetricCryptoKey>();
|
||||
async getOrgKeys(): Promise<Map<string, OrgKey>> {
|
||||
const result: Map<string, OrgKey> = new Map<string, OrgKey>();
|
||||
const decryptedOrganizationKeys = await this.stateService.getDecryptedOrganizationKeys();
|
||||
if (decryptedOrganizationKeys != null && decryptedOrganizationKeys.size > 0) {
|
||||
return decryptedOrganizationKeys;
|
||||
return decryptedOrganizationKeys as Map<string, OrgKey>;
|
||||
}
|
||||
|
||||
const encOrgKeyData = await this.stateService.getEncryptedOrganizationKeys();
|
||||
@ -305,7 +306,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
}
|
||||
|
||||
const encOrgKey = BaseEncryptedOrganizationKey.fromData(encOrgKeyData[orgId]);
|
||||
const decOrgKey = await encOrgKey.decrypt(this);
|
||||
const decOrgKey = (await encOrgKey.decrypt(this)) as OrgKey;
|
||||
result.set(orgId, decOrgKey);
|
||||
|
||||
setKey = true;
|
||||
@ -318,6 +319,15 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return result;
|
||||
}
|
||||
|
||||
async makeOrgDataEncKey(orgKey: OrgKey): Promise<[SymmetricCryptoKey, EncString]> {
|
||||
if (orgKey == null) {
|
||||
throw new Error("No Org Key provided");
|
||||
}
|
||||
|
||||
const newSymKey = await this.cryptoFunctionService.randomBytes(64);
|
||||
return this.buildProtectedSymmetricKey(orgKey, newSymKey);
|
||||
}
|
||||
|
||||
async clearOrgKeys(memoryOnly?: boolean, userId?: string): Promise<void> {
|
||||
await this.stateService.setDecryptedOrganizationKeys(null, { userId: userId });
|
||||
if (!memoryOnly) {
|
||||
@ -783,20 +793,20 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return phrase;
|
||||
}
|
||||
|
||||
private async buildProtectedUserSymKey(
|
||||
masterKey: MasterKey,
|
||||
newUserSymKey: ArrayBuffer
|
||||
): Promise<[UserSymKey, EncString]> {
|
||||
let protectedUserSymKey: EncString = null;
|
||||
if (masterKey.key.byteLength === 32) {
|
||||
const stretchedMasterKey = await this.stretchKey(masterKey);
|
||||
protectedUserSymKey = await this.encrypt(newUserSymKey, stretchedMasterKey);
|
||||
} else if (masterKey.key.byteLength === 64) {
|
||||
protectedUserSymKey = await this.encrypt(newUserSymKey, masterKey);
|
||||
private async buildProtectedSymmetricKey<T extends SymmetricCryptoKey>(
|
||||
encryptionKey: SymmetricCryptoKey,
|
||||
newSymKey: ArrayBuffer
|
||||
): Promise<[T, EncString]> {
|
||||
let protectedSymKey: EncString = null;
|
||||
if (encryptionKey.key.byteLength === 32) {
|
||||
const stretchedEncryptionKey = await this.stretchKey(encryptionKey);
|
||||
protectedSymKey = await this.encrypt(newSymKey, stretchedEncryptionKey);
|
||||
} else if (encryptionKey.key.byteLength === 64) {
|
||||
protectedSymKey = await this.encrypt(newSymKey, encryptionKey);
|
||||
} else {
|
||||
throw new Error("Invalid key size.");
|
||||
}
|
||||
return [new SymmetricCryptoKey(newUserSymKey) as UserSymKey, protectedUserSymKey];
|
||||
return [new SymmetricCryptoKey(newSymKey) as T, protectedSymKey];
|
||||
}
|
||||
|
||||
private async clearStoredUserKeys(userId?: string): Promise<void> {
|
||||
|
@ -633,10 +633,10 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
data: ArrayBuffer,
|
||||
admin = false
|
||||
): Promise<Cipher> {
|
||||
const key = await this.cryptoService.getOrgKey(cipher.organizationId);
|
||||
const encFileName = await this.cryptoService.encrypt(filename, key);
|
||||
const orgKey = await this.cryptoService.getOrgKey(cipher.organizationId);
|
||||
const encFileName = await this.cryptoService.encrypt(filename, orgKey);
|
||||
|
||||
const dataEncKey = await this.cryptoService.makeUserSymKey(key);
|
||||
const dataEncKey = await this.cryptoService.makeOrgDataEncKey(orgKey);
|
||||
const encData = await this.cryptoService.encryptToBytes(data, dataEncKey[0]);
|
||||
|
||||
const response = await this.cipherFileUploadService.upload(
|
||||
@ -946,10 +946,10 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
|
||||
const encBuf = await EncArrayBuffer.fromResponse(attachmentResponse);
|
||||
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, null);
|
||||
const key = await this.cryptoService.getOrgKey(organizationId);
|
||||
const encFileName = await this.cryptoService.encrypt(attachmentView.fileName, key);
|
||||
const orgKey = await this.cryptoService.getOrgKey(organizationId);
|
||||
const encFileName = await this.cryptoService.encrypt(attachmentView.fileName, orgKey);
|
||||
|
||||
const dataEncKey = await this.cryptoService.makeUserSymKey(key);
|
||||
const dataEncKey = await this.cryptoService.makeOrgDataEncKey(orgKey);
|
||||
const encData = await this.cryptoService.encryptToBytes(decBuf, dataEncKey[0]);
|
||||
|
||||
const fd = new FormData();
|
||||
|
Loading…
Reference in New Issue
Block a user