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:
@@ -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(() => {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user