mirror of
https://github.com/bitwarden/browser
synced 2026-02-11 14:04:03 +00:00
decrypt attachment content using sdk
This commit is contained in:
@@ -1,21 +1,25 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { OrgKey } from "@bitwarden/common/types/key";
|
||||
import { CipherEncryptionService } from "@bitwarden/common/vault/abstractions/cipher-encryption.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
@@ -56,6 +60,8 @@ export class AttachmentsComponent implements OnInit {
|
||||
protected billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
protected accountService: AccountService,
|
||||
protected toastService: ToastService,
|
||||
protected configService: ConfigService,
|
||||
protected cipherEncryptionService: CipherEncryptionService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -193,12 +199,9 @@ export class AttachmentsComponent implements OnInit {
|
||||
}
|
||||
|
||||
try {
|
||||
const encBuf = await EncArrayBuffer.fromResponse(response);
|
||||
const key =
|
||||
attachment.key != null
|
||||
? attachment.key
|
||||
: await this.keyService.getOrgKey(this.cipher.organizationId);
|
||||
const decBuf = await this.encryptService.decryptToBytes(encBuf, key);
|
||||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||
const decBuf = await this.getDecryptedBuffer(response, attachment, activeUserId);
|
||||
|
||||
this.fileDownloadService.download({
|
||||
fileName: attachment.fileName,
|
||||
blobData: decBuf,
|
||||
@@ -270,15 +273,11 @@ export class AttachmentsComponent implements OnInit {
|
||||
|
||||
try {
|
||||
// 2. Resave
|
||||
const encBuf = await EncArrayBuffer.fromResponse(response);
|
||||
const key =
|
||||
attachment.key != null
|
||||
? attachment.key
|
||||
: await this.keyService.getOrgKey(this.cipher.organizationId);
|
||||
const decBuf = await this.encryptService.decryptToBytes(encBuf, key);
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(getUserId),
|
||||
);
|
||||
const decBuf = await this.getDecryptedBuffer(response, attachment, activeUserId);
|
||||
|
||||
this.cipherDomain = await this.cipherService.saveAttachmentRawWithServer(
|
||||
this.cipherDomain,
|
||||
attachment.fileName,
|
||||
@@ -341,4 +340,39 @@ export class AttachmentsComponent implements OnInit {
|
||||
protected async reupload(attachment: AttachmentView) {
|
||||
// TODO: This should be removed but is needed since we re-use the same template
|
||||
}
|
||||
|
||||
private async getDecryptedBuffer(
|
||||
response: Response,
|
||||
attachment: AttachmentView,
|
||||
userId: UserId,
|
||||
): Promise<Uint8Array> {
|
||||
const useSdkDecryption = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.PM19941MigrateCipherDomainToSdk,
|
||||
);
|
||||
|
||||
if (useSdkDecryption) {
|
||||
const attachmentDomain = this.cipherDomain.attachments?.find((a) => a.id === attachment.id);
|
||||
|
||||
const encArrayBuf = new Uint8Array(await response.arrayBuffer());
|
||||
return await this.cipherEncryptionService.decryptAttachmentContent(
|
||||
this.cipherDomain,
|
||||
attachmentDomain,
|
||||
encArrayBuf,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
const encBuf = await EncArrayBuffer.fromResponse(response);
|
||||
const key =
|
||||
attachment.key != null
|
||||
? attachment.key
|
||||
: await firstValueFrom(
|
||||
this.keyService
|
||||
.orgKeys$(userId)
|
||||
.pipe(
|
||||
map((orgKeys) => orgKeys[this.cipher.organizationId as OrganizationId] as OrgKey),
|
||||
),
|
||||
);
|
||||
return await this.encryptService.decryptToBytes(encBuf, key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,22 +31,27 @@ import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
||||
import { CollectionId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherId, CollectionId, OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { OrgKey } from "@bitwarden/common/types/key";
|
||||
import { CipherEncryptionService } from "@bitwarden/common/vault/abstractions/cipher-encryption.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||
import { CipherType, FieldType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||
import { Launchable } from "@bitwarden/common/vault/interfaces/launchable";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
@@ -137,6 +142,8 @@ export class ViewComponent implements OnDestroy, OnInit {
|
||||
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
protected toastService: ToastService,
|
||||
private cipherAuthorizationService: CipherAuthorizationService,
|
||||
private configService: ConfigService,
|
||||
private cipherEncryptionService: CipherEncryptionService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -458,12 +465,8 @@ export class ViewComponent implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
try {
|
||||
const encBuf = await EncArrayBuffer.fromResponse(response);
|
||||
const key =
|
||||
attachment.key != null
|
||||
? attachment.key
|
||||
: await this.keyService.getOrgKey(this.cipher.organizationId);
|
||||
const decBuf = await this.encryptService.decryptToBytes(encBuf, key);
|
||||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||
const decBuf = await this.getDecryptedBuffer(response, attachment, activeUserId);
|
||||
this.fileDownloadService.download({
|
||||
fileName: attachment.fileName,
|
||||
blobData: decBuf,
|
||||
@@ -564,4 +567,41 @@ export class ViewComponent implements OnDestroy, OnInit {
|
||||
}
|
||||
this.previousCipherId = this.cipherId;
|
||||
}
|
||||
|
||||
private async getDecryptedBuffer(
|
||||
response: Response,
|
||||
attachment: AttachmentView,
|
||||
userId: UserId,
|
||||
): Promise<Uint8Array> {
|
||||
const useSdkDecryption = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.PM19941MigrateCipherDomainToSdk,
|
||||
);
|
||||
|
||||
if (useSdkDecryption) {
|
||||
const ciphersData = await firstValueFrom(this.cipherService.ciphers$(userId));
|
||||
const cipherDomain = new Cipher(ciphersData[this.cipher.id as CipherId]);
|
||||
const attachmentDomain = cipherDomain.attachments?.find((a) => a.id === attachment.id);
|
||||
|
||||
const encArrayBuf = new Uint8Array(await response.arrayBuffer());
|
||||
return await this.cipherEncryptionService.decryptAttachmentContent(
|
||||
cipherDomain,
|
||||
attachmentDomain,
|
||||
encArrayBuf,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
const encBuf = await EncArrayBuffer.fromResponse(response);
|
||||
const key =
|
||||
attachment.key != null
|
||||
? attachment.key
|
||||
: await firstValueFrom(
|
||||
this.keyService
|
||||
.orgKeys$(userId)
|
||||
.pipe(
|
||||
map((orgKeys) => orgKeys[this.cipher.organizationId as OrganizationId] as OrgKey),
|
||||
),
|
||||
);
|
||||
return await this.encryptService.decryptToBytes(encBuf, key);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user