1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

[PM-6211] Create key generation service (#7939)

* create key generation service

* replace old key generation service and add references

* use key generation service in key connector service

* use key generation service in send service

* user key generation service in access service

* use key generation service in device trust service

* fix tests

* fix browser

* add createKeyFromMaterial and tests

* create ephemeral key

* fix tests

* rename method and add returns docs

* ignore material in destructure

* modify test

* specify material as key material

* pull out magic strings to properties

* make salt optional and generate if not provided

* fix test

* fix parameters

* update docs to include link to HKDF rfc
This commit is contained in:
Jake Fink
2024-02-23 08:48:15 -05:00
committed by GitHub
parent 071959317c
commit 19a373d87e
27 changed files with 401 additions and 149 deletions

View File

@@ -1,10 +1,10 @@
import { any, mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject, firstValueFrom } from "rxjs";
import { CryptoFunctionService } from "../../../platform/abstractions/crypto-function.service";
import { CryptoService } from "../../../platform/abstractions/crypto.service";
import { EncryptService } from "../../../platform/abstractions/encrypt.service";
import { I18nService } from "../../../platform/abstractions/i18n.service";
import { KeyGenerationService } from "../../../platform/abstractions/key-generation.service";
import { StateService } from "../../../platform/abstractions/state.service";
import { EncString } from "../../../platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
@@ -24,7 +24,7 @@ import { SendService } from "./send.service";
describe("SendService", () => {
const cryptoService = mock<CryptoService>();
const i18nService = mock<I18nService>();
const cryptoFunctionService = mock<CryptoFunctionService>();
const keyGenerationService = mock<KeyGenerationService>();
const encryptService = mock<EncryptService>();
let sendService: SendService;
@@ -50,7 +50,7 @@ describe("SendService", () => {
.calledWith(any())
.mockResolvedValue([sendView("1", "Test Send")]);
sendService = new SendService(cryptoService, i18nService, cryptoFunctionService, stateService);
sendService = new SendService(cryptoService, i18nService, keyGenerationService, stateService);
});
afterEach(() => {

View File

@@ -1,9 +1,10 @@
import { BehaviorSubject, Observable, concatMap, distinctUntilChanged, map } from "rxjs";
import { CryptoFunctionService } from "../../../platform/abstractions/crypto-function.service";
import { CryptoService } from "../../../platform/abstractions/crypto.service";
import { I18nService } from "../../../platform/abstractions/i18n.service";
import { KeyGenerationService } from "../../../platform/abstractions/key-generation.service";
import { StateService } from "../../../platform/abstractions/state.service";
import { KdfType } from "../../../platform/enums";
import { Utils } from "../../../platform/misc/utils";
import { EncArrayBuffer } from "../../../platform/models/domain/enc-array-buffer";
import { EncString } from "../../../platform/models/domain/enc-string";
@@ -21,6 +22,9 @@ import { SEND_KDF_ITERATIONS } from "../send-kdf";
import { InternalSendService as InternalSendServiceAbstraction } from "./send.service.abstraction";
export class SendService implements InternalSendServiceAbstraction {
readonly sendKeySalt = "bitwarden-send";
readonly sendKeyPurpose = "send";
protected _sends: BehaviorSubject<Send[]> = new BehaviorSubject([]);
protected _sendViews: BehaviorSubject<SendView[]> = new BehaviorSubject([]);
@@ -30,7 +34,7 @@ export class SendService implements InternalSendServiceAbstraction {
constructor(
private cryptoService: CryptoService,
private i18nService: I18nService,
private cryptoFunctionService: CryptoFunctionService,
private keyGenerationService: KeyGenerationService,
private stateService: StateService,
) {
this.stateService.activeAccountUnlocked$
@@ -72,17 +76,22 @@ export class SendService implements InternalSendServiceAbstraction {
send.hideEmail = model.hideEmail;
send.maxAccessCount = model.maxAccessCount;
if (model.key == null) {
model.key = await this.cryptoFunctionService.aesGenerateKey(128);
model.cryptoKey = await this.cryptoService.makeSendKey(model.key);
const key = await this.keyGenerationService.createKeyWithPurpose(
128,
this.sendKeyPurpose,
this.sendKeySalt,
);
model.key = key.material;
model.cryptoKey = key.derivedKey;
}
if (password != null) {
const passwordHash = await this.cryptoFunctionService.pbkdf2(
const passwordKey = await this.keyGenerationService.deriveKeyFromPassword(
password,
model.key,
"sha256",
SEND_KDF_ITERATIONS,
KdfType.PBKDF2_SHA256,
{ iterations: SEND_KDF_ITERATIONS },
);
send.password = Utils.fromBufferToB64(passwordHash);
send.password = passwordKey.keyB64;
}
send.key = await this.cryptoService.encrypt(model.key, key);
send.name = await this.cryptoService.encrypt(model.name, model.cryptoKey);