support for new attachment keys
This commit is contained in:
parent
c297728967
commit
17e7ee4838
|
@ -143,7 +143,8 @@ export class AttachmentsComponent implements OnInit {
|
|||
|
||||
try {
|
||||
const buf = await response.arrayBuffer();
|
||||
const key = await this.cryptoService.getOrgKey(this.cipher.organizationId);
|
||||
const key = attachment.key != null ? attachment.key :
|
||||
await this.cryptoService.getOrgKey(this.cipher.organizationId);
|
||||
const decBuf = await this.cryptoService.decryptFromBytes(buf, key);
|
||||
this.platformUtilsService.saveFile(this.win, decBuf, null, attachment.fileName);
|
||||
} catch (e) {
|
||||
|
|
|
@ -171,7 +171,8 @@ export class ViewComponent implements OnDestroy, OnInit {
|
|||
|
||||
try {
|
||||
const buf = await response.arrayBuffer();
|
||||
const key = await this.cryptoService.getOrgKey(this.cipher.organizationId);
|
||||
const key = attachment.key != null ? attachment.key :
|
||||
await this.cryptoService.getOrgKey(this.cipher.organizationId);
|
||||
const decBuf = await this.cryptoService.decryptFromBytes(buf, key);
|
||||
this.platformUtilsService.saveFile(this.win, decBuf, null, attachment.fileName);
|
||||
} catch (e) {
|
||||
|
|
|
@ -4,6 +4,7 @@ export class AttachmentData {
|
|||
id: string;
|
||||
url: string;
|
||||
fileName: string;
|
||||
key: string;
|
||||
size: number;
|
||||
sizeName: string;
|
||||
|
||||
|
@ -14,6 +15,7 @@ export class AttachmentData {
|
|||
this.id = response.id;
|
||||
this.url = response.url;
|
||||
this.fileName = response.fileName;
|
||||
this.key = response.key;
|
||||
this.size = response.size;
|
||||
this.sizeName = response.sizeName;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
import { AttachmentData } from '../data/attachmentData';
|
||||
|
||||
import { AttachmentView } from '../view/attachmentView';
|
||||
|
||||
import { CipherString } from './cipherString';
|
||||
import Domain from './domainBase';
|
||||
import { SymmetricCryptoKey } from './symmetricCryptoKey';
|
||||
|
||||
import { AttachmentView } from '../view/attachmentView';
|
||||
import { CryptoService } from '../../abstractions/crypto.service';
|
||||
|
||||
import { Utils } from '../../misc/utils';
|
||||
|
||||
export class Attachment extends Domain {
|
||||
id: string;
|
||||
url: string;
|
||||
size: number;
|
||||
sizeName: string;
|
||||
key: CipherString;
|
||||
fileName: CipherString;
|
||||
|
||||
constructor(obj?: AttachmentData, alreadyEncrypted: boolean = false) {
|
||||
|
@ -24,13 +30,34 @@ export class Attachment extends Domain {
|
|||
url: null,
|
||||
sizeName: null,
|
||||
fileName: null,
|
||||
key: null,
|
||||
}, alreadyEncrypted, ['id', 'url', 'sizeName']);
|
||||
}
|
||||
|
||||
decrypt(orgId: string): Promise<AttachmentView> {
|
||||
return this.decryptObj(new AttachmentView(this), {
|
||||
async decrypt(orgId: string): Promise<AttachmentView> {
|
||||
const view = await this.decryptObj(new AttachmentView(this), {
|
||||
fileName: null,
|
||||
}, orgId);
|
||||
|
||||
if (this.key != null) {
|
||||
let cryptoService: CryptoService;
|
||||
const containerService = (Utils.global as any).bitwardenContainerService;
|
||||
if (containerService) {
|
||||
cryptoService = containerService.getCryptoService();
|
||||
} else {
|
||||
throw new Error('global bitwardenContainerService not initialized.');
|
||||
}
|
||||
|
||||
try {
|
||||
const orgKey = await cryptoService.getOrgKey(orgId);
|
||||
const decValue = await cryptoService.decryptToBytes(this.key, orgKey);
|
||||
view.key = new SymmetricCryptoKey(decValue);
|
||||
} catch (e) {
|
||||
// TODO: error?
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
toAttachmentData(): AttachmentData {
|
||||
|
@ -40,6 +67,7 @@ export class Attachment extends Domain {
|
|||
url: null,
|
||||
sizeName: null,
|
||||
fileName: null,
|
||||
key: null,
|
||||
}, ['id', 'url', 'sizeName']);
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
export class AttachmentRequest {
|
||||
fileName: string;
|
||||
key: string;
|
||||
}
|
|
@ -8,6 +8,7 @@ import { IdentityApi } from '../api/identityApi';
|
|||
import { LoginApi } from '../api/loginApi';
|
||||
import { SecureNoteApi } from '../api/secureNoteApi';
|
||||
|
||||
import { AttachmentRequest } from './attachmentRequest';
|
||||
import { PasswordHistoryRequest } from './passwordHistoryRequest';
|
||||
|
||||
export class CipherRequest {
|
||||
|
@ -23,7 +24,9 @@ export class CipherRequest {
|
|||
identity: IdentityApi;
|
||||
fields: FieldApi[];
|
||||
passwordHistory: PasswordHistoryRequest[];
|
||||
// Deprecated, remove at some point and rename attachments2 to attachments
|
||||
attachments: { [id: string]: string; };
|
||||
attachments2: { [id: string]: AttachmentRequest; };
|
||||
|
||||
constructor(cipher: Cipher) {
|
||||
this.type = cipher.type;
|
||||
|
@ -119,8 +122,16 @@ export class CipherRequest {
|
|||
|
||||
if (cipher.attachments) {
|
||||
this.attachments = {};
|
||||
this.attachments2 = {};
|
||||
cipher.attachments.forEach((attachment) => {
|
||||
this.attachments[attachment.id] = attachment.fileName ? attachment.fileName.encryptedString : null;
|
||||
const fileName = attachment.fileName ? attachment.fileName.encryptedString : null;
|
||||
this.attachments[attachment.id] = fileName;
|
||||
const attachmentRequest = new AttachmentRequest();
|
||||
attachmentRequest.fileName = fileName;
|
||||
if (attachment.key != null) {
|
||||
attachmentRequest.key = attachment.key.encryptedString;
|
||||
}
|
||||
this.attachments2[attachment.id] = attachmentRequest;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ export class AttachmentResponse {
|
|||
id: string;
|
||||
url: string;
|
||||
fileName: string;
|
||||
key: string;
|
||||
size: number;
|
||||
sizeName: string;
|
||||
|
||||
|
@ -9,6 +10,7 @@ export class AttachmentResponse {
|
|||
this.id = response.Id;
|
||||
this.url = response.Url;
|
||||
this.fileName = response.FileName;
|
||||
this.key = response.Key;
|
||||
this.size = response.Size;
|
||||
this.sizeName = response.SizeName;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { View } from './view';
|
||||
|
||||
import { Attachment } from '../domain/attachment';
|
||||
import { SymmetricCryptoKey } from '../domain/symmetricCryptoKey';
|
||||
|
||||
export class AttachmentView implements View {
|
||||
id: string;
|
||||
|
@ -8,6 +9,7 @@ export class AttachmentView implements View {
|
|||
size: number;
|
||||
sizeName: string;
|
||||
fileName: string;
|
||||
key: SymmetricCryptoKey;
|
||||
|
||||
constructor(a?: Attachment) {
|
||||
if (!a) {
|
||||
|
|
|
@ -173,7 +173,10 @@ export class CipherService implements CipherServiceAbstraction {
|
|||
attachment.url = model.url;
|
||||
const promise = this.encryptObjProperty(model, attachment, {
|
||||
fileName: null,
|
||||
}, key).then(() => {
|
||||
}, key).then(async () => {
|
||||
if (model.key != null) {
|
||||
attachment.key = await this.cryptoService.encrypt(model.key.key, key);
|
||||
}
|
||||
encAttachments.push(attachment);
|
||||
});
|
||||
promises.push(promise);
|
||||
|
@ -519,14 +522,18 @@ 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 encData = await this.cryptoService.encryptToBytes(data, key);
|
||||
|
||||
const dataEncKey = await this.cryptoService.makeEncKey(key);
|
||||
const encData = await this.cryptoService.encryptToBytes(data, dataEncKey[0]);
|
||||
|
||||
const fd = new FormData();
|
||||
try {
|
||||
fd.append('key', dataEncKey[1].encryptedString);
|
||||
const blob = new Blob([encData], { type: 'application/octet-stream' });
|
||||
fd.append('data', blob, encFileName.encryptedString);
|
||||
} catch (e) {
|
||||
if (Utils.isNode && !Utils.isBrowser) {
|
||||
fd.append('key', dataEncKey[1].encryptedString);
|
||||
fd.append('data', Buffer.from(encData) as any, {
|
||||
filepath: encFileName.encryptedString,
|
||||
contentType: 'application/octet-stream',
|
||||
|
@ -753,15 +760,19 @@ export class CipherService implements CipherServiceAbstraction {
|
|||
const buf = await attachmentResponse.arrayBuffer();
|
||||
const decBuf = await this.cryptoService.decryptFromBytes(buf, null);
|
||||
const key = await this.cryptoService.getOrgKey(organizationId);
|
||||
const encData = await this.cryptoService.encryptToBytes(decBuf, key);
|
||||
const encFileName = await this.cryptoService.encrypt(attachmentView.fileName, key);
|
||||
|
||||
const dataEncKey = await this.cryptoService.makeEncKey(key);
|
||||
const encData = await this.cryptoService.encryptToBytes(decBuf, dataEncKey[0]);
|
||||
|
||||
const fd = new FormData();
|
||||
try {
|
||||
fd.append('key', dataEncKey[1].encryptedString);
|
||||
const blob = new Blob([encData], { type: 'application/octet-stream' });
|
||||
fd.append('data', blob, encFileName.encryptedString);
|
||||
} catch (e) {
|
||||
if (Utils.isNode && !Utils.isBrowser) {
|
||||
fd.append('key', dataEncKey[1].encryptedString);
|
||||
fd.append('data', Buffer.from(encData) as any, {
|
||||
filepath: encFileName.encryptedString,
|
||||
contentType: 'application/octet-stream',
|
||||
|
|
|
@ -333,8 +333,9 @@ export class CryptoService implements CryptoServiceAbstraction {
|
|||
}
|
||||
|
||||
async makeEncKey(key: SymmetricCryptoKey): Promise<[SymmetricCryptoKey, CipherString]> {
|
||||
const theKey = await this.getKeyForEncryption(key);
|
||||
const encKey = await this.cryptoFunctionService.randomBytes(64);
|
||||
return this.buildEncKey(key, encKey);
|
||||
return this.buildEncKey(theKey, encKey);
|
||||
}
|
||||
|
||||
async remakeEncKey(key: SymmetricCryptoKey): Promise<[SymmetricCryptoKey, CipherString]> {
|
||||
|
|
Loading…
Reference in New Issue