support for new attachment keys

This commit is contained in:
Kyle Spearrin 2018-11-13 20:43:45 -05:00
parent c297728967
commit 17e7ee4838
10 changed files with 73 additions and 10 deletions

View File

@ -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) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -0,0 +1,4 @@
export class AttachmentRequest {
fileName: string;
key: string;
}

View File

@ -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;
});
}
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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',

View File

@ -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]> {