Skip to content
This repository has been archived by the owner on Jun 17, 2022. It is now read-only.

Commit

Permalink
support for new attachment keys
Browse files Browse the repository at this point in the history
  • Loading branch information
kspearrin committed Nov 14, 2018
1 parent c297728 commit 17e7ee4
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 10 deletions.
3 changes: 2 additions & 1 deletion src/angular/components/attachments.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion src/angular/components/view.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions src/models/data/attachmentData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export class AttachmentData {
id: string;
url: string;
fileName: string;
key: string;
size: number;
sizeName: string;

Expand All @@ -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;
}
Expand Down
34 changes: 31 additions & 3 deletions src/models/domain/attachment.ts
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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 {
Expand All @@ -40,6 +67,7 @@ export class Attachment extends Domain {
url: null,
sizeName: null,
fileName: null,
key: null,
}, ['id', 'url', 'sizeName']);
return a;
}
Expand Down
4 changes: 4 additions & 0 deletions src/models/request/attachmentRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class AttachmentRequest {
fileName: string;
key: string;
}
13 changes: 12 additions & 1 deletion src/models/request/cipherRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -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;
});
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/models/response/attachmentResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ export class AttachmentResponse {
id: string;
url: string;
fileName: string;
key: string;
size: number;
sizeName: string;

constructor(response: any) {
this.id = response.Id;
this.url = response.Url;
this.fileName = response.FileName;
this.key = response.Key;
this.size = response.Size;
this.sizeName = response.SizeName;
}
Expand Down
2 changes: 2 additions & 0 deletions src/models/view/attachmentView.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { View } from './view';

import { Attachment } from '../domain/attachment';
import { SymmetricCryptoKey } from '../domain/symmetricCryptoKey';

export class AttachmentView implements View {
id: string;
url: string;
size: number;
sizeName: string;
fileName: string;
key: SymmetricCryptoKey;

constructor(a?: Attachment) {
if (!a) {
Expand Down
17 changes: 14 additions & 3 deletions src/services/cipher.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
3 changes: 2 additions & 1 deletion src/services/crypto.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]> {
Expand Down

0 comments on commit 17e7ee4

Please sign in to comment.