diff --git a/src/background/main.background.ts b/src/background/main.background.ts index 758573a2ac..069efcbf13 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -1,7 +1,5 @@ import { Abstractions, Enums, Services } from '@bitwarden/jslib'; -import { Cipher } from '../models/domain/cipher'; - import BrowserApi from '../browser/browserApi'; import CommandsBackground from './commands.background'; diff --git a/src/models/domain/attachment.ts b/src/models/domain/attachment.ts deleted file mode 100644 index 9957172f31..0000000000 --- a/src/models/domain/attachment.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Data } from '@bitwarden/jslib'; - -import { CipherString } from './cipherString'; -import Domain from './domain'; - -class Attachment extends Domain { - id: string; - url: string; - size: number; - sizeName: string; - fileName: CipherString; - - constructor(obj?: Data.Attachment, alreadyEncrypted: boolean = false) { - super(); - if (obj == null) { - return; - } - - this.size = obj.size; - this.buildDomainModel(this, obj, { - id: null, - url: null, - sizeName: null, - fileName: null, - }, alreadyEncrypted, ['id', 'url', 'sizeName']); - } - - decrypt(orgId: string): Promise { - const model = { - id: this.id, - size: this.size, - sizeName: this.sizeName, - url: this.url, - }; - - return this.decryptObj(model, { - fileName: null, - }, orgId); - } -} - -export { Attachment }; -(window as any).Attachment = Attachment; diff --git a/src/models/domain/card.ts b/src/models/domain/card.ts deleted file mode 100644 index d8e2b99691..0000000000 --- a/src/models/domain/card.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Data } from '@bitwarden/jslib'; - -import { CipherString } from './cipherString'; -import Domain from './domain'; - -class Card extends Domain { - cardholderName: CipherString; - brand: CipherString; - number: CipherString; - expMonth: CipherString; - expYear: CipherString; - code: CipherString; - - constructor(obj?: Data.Card, alreadyEncrypted: boolean = false) { - super(); - if (obj == null) { - return; - } - - this.buildDomainModel(this, obj, { - cardholderName: null, - brand: null, - number: null, - expMonth: null, - expYear: null, - code: null, - }, alreadyEncrypted, []); - } - - decrypt(orgId: string): Promise { - return this.decryptObj({}, { - cardholderName: null, - brand: null, - number: null, - expMonth: null, - expYear: null, - code: null, - }, orgId); - } -} - -export { Card }; -(window as any).Card = Card; diff --git a/src/models/domain/cipher.ts b/src/models/domain/cipher.ts deleted file mode 100644 index 038efe1c46..0000000000 --- a/src/models/domain/cipher.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { Abstractions, Enums, Data } from '@bitwarden/jslib'; - -import { Attachment } from './attachment'; -import { Card } from './card'; -import { CipherString } from './cipherString'; -import Domain from './domain'; -import { Field } from './field'; -import { Identity } from './identity'; -import { Login } from './login'; -import { SecureNote } from './secureNote'; - -class Cipher extends Domain { - id: string; - organizationId: string; - folderId: string; - name: CipherString; - notes: CipherString; - type: Enums.CipherType; - favorite: boolean; - organizationUseTotp: boolean; - edit: boolean; - localData: any; - login: Login; - identity: Identity; - card: Card; - secureNote: SecureNote; - attachments: Attachment[]; - fields: Field[]; - collectionIds: string[]; - - constructor(obj?: Data.Cipher, alreadyEncrypted: boolean = false, localData: any = null) { - super(); - if (obj == null) { - return; - } - - this.buildDomainModel(this, obj, { - id: null, - organizationId: null, - folderId: null, - name: null, - notes: null, - }, alreadyEncrypted, ['id', 'organizationId', 'folderId']); - - this.type = obj.type; - this.favorite = obj.favorite; - this.organizationUseTotp = obj.organizationUseTotp; - this.edit = obj.edit; - this.collectionIds = obj.collectionIds; - this.localData = localData; - - switch (this.type) { - case Enums.CipherType.Login: - this.login = new Login(obj.login, alreadyEncrypted); - break; - case Enums.CipherType.SecureNote: - this.secureNote = new SecureNote(obj.secureNote, alreadyEncrypted); - break; - case Enums.CipherType.Card: - this.card = new Card(obj.card, alreadyEncrypted); - break; - case Enums.CipherType.Identity: - this.identity = new Identity(obj.identity, alreadyEncrypted); - break; - default: - break; - } - - if (obj.attachments != null) { - this.attachments = []; - obj.attachments.forEach((attachment) => { - this.attachments.push(new Attachment(attachment, alreadyEncrypted)); - }); - } else { - this.attachments = null; - } - - if (obj.fields != null) { - this.fields = []; - obj.fields.forEach((field) => { - this.fields.push(new Field(field, alreadyEncrypted)); - }); - } else { - this.fields = null; - } - } - - async decrypt(): Promise { - const model = { - id: this.id, - organizationId: this.organizationId, - folderId: this.folderId, - favorite: this.favorite, - type: this.type, - localData: this.localData, - login: null as any, - card: null as any, - identity: null as any, - secureNote: null as any, - subTitle: null as string, - attachments: null as any[], - fields: null as any[], - collectionIds: this.collectionIds, - }; - - await this.decryptObj(model, { - name: null, - notes: null, - }, this.organizationId); - - switch (this.type) { - case Enums.CipherType.Login: - model.login = await this.login.decrypt(this.organizationId); - model.subTitle = model.login.username; - if (model.login.uri) { - const containerService = (window as any).BitwardenContainerService; - if (containerService) { - const platformUtilsService: Abstractions.PlatformUtilsService = - containerService.getPlatformUtilsService(); - model.login.domain = platformUtilsService.getDomain(model.login.uri); - } else { - throw new Error('window.BitwardenContainerService not initialized.'); - } - } - break; - case Enums.CipherType.SecureNote: - model.secureNote = await this.secureNote.decrypt(this.organizationId); - model.subTitle = null; - break; - case Enums.CipherType.Card: - model.card = await this.card.decrypt(this.organizationId); - model.subTitle = model.card.brand; - if (model.card.number && model.card.number.length >= 4) { - if (model.subTitle !== '') { - model.subTitle += ', '; - } - model.subTitle += ('*' + model.card.number.substr(model.card.number.length - 4)); - } - break; - case Enums.CipherType.Identity: - model.identity = await this.identity.decrypt(this.organizationId); - model.subTitle = ''; - if (model.identity.firstName) { - model.subTitle = model.identity.firstName; - } - if (model.identity.lastName) { - if (model.subTitle !== '') { - model.subTitle += ' '; - } - model.subTitle += model.identity.lastName; - } - break; - default: - break; - } - - const orgId = this.organizationId; - - if (this.attachments != null && this.attachments.length > 0) { - const attachments: any[] = []; - await this.attachments.reduce((promise, attachment) => { - return promise.then(() => { - return attachment.decrypt(orgId); - }).then((decAttachment) => { - attachments.push(decAttachment); - }); - }, Promise.resolve()); - model.attachments = attachments; - } - - if (this.fields != null && this.fields.length > 0) { - const fields: any[] = []; - await this.fields.reduce((promise, field) => { - return promise.then(() => { - return field.decrypt(orgId); - }).then((decField) => { - fields.push(decField); - }); - }, Promise.resolve()); - model.fields = fields; - } - - return model; - } -} - -export { Cipher }; -(window as any).Cipher = Cipher; diff --git a/src/models/domain/cipherString.ts b/src/models/domain/cipherString.ts deleted file mode 100644 index 3dc5d64510..0000000000 --- a/src/models/domain/cipherString.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { Enums } from '@bitwarden/jslib'; - -import { CryptoService } from '../../services/abstractions/crypto.service'; - -class CipherString { - encryptedString?: string; - encryptionType?: Enums.EncryptionType; - decryptedValue?: string; - cipherText?: string; - initializationVector?: string; - mac?: string; - - constructor(encryptedStringOrType: string | Enums.EncryptionType, ct?: string, iv?: string, mac?: string) { - if (ct != null) { - // ct and header - const encType = encryptedStringOrType as Enums.EncryptionType; - this.encryptedString = encType + '.' + ct; - - // iv - if (iv != null) { - this.encryptedString += ('|' + iv); - } - - // mac - if (mac != null) { - this.encryptedString += ('|' + mac); - } - - this.encryptionType = encType; - this.cipherText = ct; - this.initializationVector = iv; - this.mac = mac; - - return; - } - - this.encryptedString = encryptedStringOrType as string; - if (!this.encryptedString) { - return; - } - - const headerPieces = this.encryptedString.split('.'); - let encPieces: string[] = null; - - if (headerPieces.length === 2) { - try { - this.encryptionType = parseInt(headerPieces[0], null); - encPieces = headerPieces[1].split('|'); - } catch (e) { - return; - } - } else { - encPieces = this.encryptedString.split('|'); - this.encryptionType = encPieces.length === 3 ? Enums.EncryptionType.AesCbc128_HmacSha256_B64 : - Enums.EncryptionType.AesCbc256_B64; - } - - switch (this.encryptionType) { - case Enums.EncryptionType.AesCbc128_HmacSha256_B64: - case Enums.EncryptionType.AesCbc256_HmacSha256_B64: - if (encPieces.length !== 3) { - return; - } - - this.initializationVector = encPieces[0]; - this.cipherText = encPieces[1]; - this.mac = encPieces[2]; - break; - case Enums.EncryptionType.AesCbc256_B64: - if (encPieces.length !== 2) { - return; - } - - this.initializationVector = encPieces[0]; - this.cipherText = encPieces[1]; - break; - case Enums.EncryptionType.Rsa2048_OaepSha256_B64: - case Enums.EncryptionType.Rsa2048_OaepSha1_B64: - if (encPieces.length !== 1) { - return; - } - - this.cipherText = encPieces[0]; - break; - default: - return; - } - } - - decrypt(orgId: string): Promise { - if (this.decryptedValue) { - return Promise.resolve(this.decryptedValue); - } - - let cryptoService: CryptoService; - const containerService = (window as any).BitwardenContainerService; - if (containerService) { - cryptoService = containerService.getCryptoService(); - } else { - throw new Error('window.BitwardenContainerService not initialized.'); - } - - return cryptoService.getOrgKey(orgId).then((orgKey: any) => { - return cryptoService.decrypt(this, orgKey); - }).then((decValue: any) => { - this.decryptedValue = decValue; - return this.decryptedValue; - }).catch(() => { - this.decryptedValue = '[error: cannot decrypt]'; - return this.decryptedValue; - }); - } -} - -export { CipherString }; -(window as any).CipherString = CipherString; diff --git a/src/models/domain/collection.ts b/src/models/domain/collection.ts deleted file mode 100644 index 7d6b75a029..0000000000 --- a/src/models/domain/collection.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Data } from '@bitwarden/jslib'; - -import { CipherString } from './cipherString'; -import Domain from './domain'; - -class Collection extends Domain { - id: string; - organizationId: string; - name: CipherString; - - constructor(obj?: Data.Collection, alreadyEncrypted: boolean = false) { - super(); - if (obj == null) { - return; - } - - this.buildDomainModel(this, obj, { - id: null, - organizationId: null, - name: null, - }, alreadyEncrypted, ['id', 'organizationId']); - } - - decrypt(): Promise { - const model = { - id: this.id, - organizationId: this.organizationId, - }; - - return this.decryptObj(model, { - name: null, - }, this.organizationId); - } -} - -export { Collection }; -(window as any).Collection = Collection; diff --git a/src/models/domain/domain.ts b/src/models/domain/domain.ts deleted file mode 100644 index cdb220776b..0000000000 --- a/src/models/domain/domain.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { CipherString } from '../domain/cipherString'; - -export default abstract class Domain { - protected buildDomainModel(model: any, obj: any, map: any, alreadyEncrypted: boolean, notEncList: any[] = []) { - for (const prop in map) { - if (!map.hasOwnProperty(prop)) { - continue; - } - - const objProp = obj[(map[prop] || prop)]; - if (alreadyEncrypted === true || notEncList.indexOf(prop) > -1) { - model[prop] = objProp ? objProp : null; - } else { - model[prop] = objProp ? new CipherString(objProp) : null; - } - } - } - - protected async decryptObj(model: any, map: any, orgId: string) { - const promises = []; - const self: any = this; - - for (const prop in map) { - if (!map.hasOwnProperty(prop)) { - continue; - } - - // tslint:disable-next-line - (function (theProp) { - const p = Promise.resolve().then(() => { - const mapProp = map[theProp] || theProp; - if (self[mapProp]) { - return self[mapProp].decrypt(orgId); - } - return null; - }).then((val: any) => { - model[theProp] = val; - }); - promises.push(p); - })(prop); - } - - await Promise.all(promises); - return model; - } -} diff --git a/src/models/domain/encryptedObject.ts b/src/models/domain/encryptedObject.ts deleted file mode 100644 index 668c30e262..0000000000 --- a/src/models/domain/encryptedObject.ts +++ /dev/null @@ -1,8 +0,0 @@ -import SymmetricCryptoKey from './symmetricCryptoKey'; - -export default class EncryptedObject { - iv: Uint8Array; - ct: Uint8Array; - mac: Uint8Array; - key: SymmetricCryptoKey; -} diff --git a/src/models/domain/environmentUrls.ts b/src/models/domain/environmentUrls.ts deleted file mode 100644 index 0eec60a114..0000000000 --- a/src/models/domain/environmentUrls.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default class EnvironmentUrls { - base: string; - api: string; - identity: string; -} diff --git a/src/models/domain/field.ts b/src/models/domain/field.ts deleted file mode 100644 index 0387e530e2..0000000000 --- a/src/models/domain/field.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Enums, Data } from '@bitwarden/jslib'; - -import { CipherString } from './cipherString'; -import Domain from './domain'; - -class Field extends Domain { - name: CipherString; - vault: CipherString; - type: Enums.FieldType; - - constructor(obj?: Data.Field, alreadyEncrypted: boolean = false) { - super(); - if (obj == null) { - return; - } - - this.type = obj.type; - this.buildDomainModel(this, obj, { - name: null, - value: null, - }, alreadyEncrypted, []); - } - - decrypt(orgId: string): Promise { - const model = { - type: this.type, - }; - - return this.decryptObj(model, { - name: null, - value: null, - }, orgId); - } -} - -export { Field }; -(window as any).Field = Field; diff --git a/src/models/domain/identity.ts b/src/models/domain/identity.ts deleted file mode 100644 index f49ce8f47b..0000000000 --- a/src/models/domain/identity.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Data } from '@bitwarden/jslib'; - -import { CipherString } from './cipherString'; -import Domain from './domain'; - -class Identity extends Domain { - title: CipherString; - firstName: CipherString; - middleName: CipherString; - lastName: CipherString; - address1: CipherString; - address2: CipherString; - address3: CipherString; - city: CipherString; - state: CipherString; - postalCode: CipherString; - country: CipherString; - company: CipherString; - email: CipherString; - phone: CipherString; - ssn: CipherString; - username: CipherString; - passportNumber: CipherString; - licenseNumber: CipherString; - - constructor(obj?: Data.Identity, alreadyEncrypted: boolean = false) { - super(); - if (obj == null) { - return; - } - - this.buildDomainModel(this, obj, { - title: null, - firstName: null, - middleName: null, - lastName: null, - address1: null, - address2: null, - address3: null, - city: null, - state: null, - postalCode: null, - country: null, - company: null, - email: null, - phone: null, - ssn: null, - username: null, - passportNumber: null, - licenseNumber: null, - }, alreadyEncrypted, []); - } - - decrypt(orgId: string): Promise { - return this.decryptObj({}, { - title: null, - firstName: null, - middleName: null, - lastName: null, - address1: null, - address2: null, - address3: null, - city: null, - state: null, - postalCode: null, - country: null, - company: null, - email: null, - phone: null, - ssn: null, - username: null, - passportNumber: null, - licenseNumber: null, - }, orgId); - } -} - -export { Identity }; -(window as any).Identity = Identity; diff --git a/src/models/domain/login.ts b/src/models/domain/login.ts deleted file mode 100644 index 73bd237399..0000000000 --- a/src/models/domain/login.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Data } from '@bitwarden/jslib'; - -import { CipherString } from './cipherString'; -import Domain from './domain'; - -class Login extends Domain { - uri: CipherString; - username: CipherString; - password: CipherString; - totp: CipherString; - - constructor(obj?: Data.Login, alreadyEncrypted: boolean = false) { - super(); - if (obj == null) { - return; - } - - this.buildDomainModel(this, obj, { - uri: null, - username: null, - password: null, - totp: null, - }, alreadyEncrypted, []); - } - - decrypt(orgId: string): Promise { - return this.decryptObj({}, { - uri: null, - username: null, - password: null, - totp: null, - }, orgId); - } -} - -export { Login }; -(window as any).Login = Login; diff --git a/src/models/domain/passwordHistory.ts b/src/models/domain/passwordHistory.ts deleted file mode 100644 index fc4eb56688..0000000000 --- a/src/models/domain/passwordHistory.ts +++ /dev/null @@ -1,9 +0,0 @@ -export default class PasswordHistory { - password: string; - date: number; - - constructor(password: string, date: number) { - this.password = password; - this.date = date; - } -} diff --git a/src/models/domain/secureNote.ts b/src/models/domain/secureNote.ts deleted file mode 100644 index 97cbd9044e..0000000000 --- a/src/models/domain/secureNote.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Enums, Data } from '@bitwarden/jslib'; - -import Domain from './domain'; - -class SecureNote extends Domain { - type: Enums.SecureNoteType; - - constructor(obj?: Data.SecureNote, alreadyEncrypted: boolean = false) { - super(); - if (obj == null) { - return; - } - - this.type = obj.type; - } - - decrypt(orgId: string): any { - return { - type: this.type, - }; - } -} - -export { SecureNote }; -(window as any).SecureNote = SecureNote; diff --git a/src/models/domain/symmetricCryptoKey.ts b/src/models/domain/symmetricCryptoKey.ts deleted file mode 100644 index 3cf6e91986..0000000000 --- a/src/models/domain/symmetricCryptoKey.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as forge from 'node-forge'; - -import { Enums, Services } from '@bitwarden/jslib'; - -import SymmetricCryptoKeyBuffers from './symmetricCryptoKeyBuffers'; - -export default class SymmetricCryptoKey { - key: string; - keyB64: string; - encKey: string; - macKey: string; - encType: Enums.EncryptionType; - keyBuf: SymmetricCryptoKeyBuffers; - - constructor(keyBytes: string, b64KeyBytes?: boolean, encType?: Enums.EncryptionType) { - if (b64KeyBytes) { - keyBytes = forge.util.decode64(keyBytes); - } - - if (!keyBytes) { - throw new Error('Must provide keyBytes'); - } - - const buffer = (forge as any).util.createBuffer(keyBytes); - if (!buffer || buffer.length() === 0) { - throw new Error('Couldn\'t make buffer'); - } - - const bufferLength: number = buffer.length(); - - if (encType == null) { - if (bufferLength === 32) { - encType = Enums.EncryptionType.AesCbc256_B64; - } else if (bufferLength === 64) { - encType = Enums.EncryptionType.AesCbc256_HmacSha256_B64; - } else { - throw new Error('Unable to determine encType.'); - } - } - - this.key = keyBytes; - this.keyB64 = forge.util.encode64(keyBytes); - this.encType = encType; - - if (encType === Enums.EncryptionType.AesCbc256_B64 && bufferLength === 32) { - this.encKey = keyBytes; - this.macKey = null; - } else if (encType === Enums.EncryptionType.AesCbc128_HmacSha256_B64 && bufferLength === 32) { - this.encKey = buffer.getBytes(16); // first half - this.macKey = buffer.getBytes(16); // second half - } else if (encType === Enums.EncryptionType.AesCbc256_HmacSha256_B64 && bufferLength === 64) { - this.encKey = buffer.getBytes(32); // first half - this.macKey = buffer.getBytes(32); // second half - } else { - throw new Error('Unsupported encType/key length.'); - } - } - - getBuffers() { - if (this.keyBuf) { - return this.keyBuf; - } - - const key = Services.UtilsService.fromB64ToArray(this.keyB64); - const keys = new SymmetricCryptoKeyBuffers(key.buffer); - - if (this.macKey) { - keys.encKey = key.slice(0, key.length / 2).buffer; - keys.macKey = key.slice(key.length / 2).buffer; - } else { - keys.encKey = key.buffer; - keys.macKey = null; - } - - this.keyBuf = keys; - return this.keyBuf; - } -} diff --git a/src/models/domain/symmetricCryptoKeyBuffers.ts b/src/models/domain/symmetricCryptoKeyBuffers.ts deleted file mode 100644 index 5a378ad246..0000000000 --- a/src/models/domain/symmetricCryptoKeyBuffers.ts +++ /dev/null @@ -1,9 +0,0 @@ -export default class SymmetricCryptoKeyBuffers { - key: ArrayBuffer; - encKey?: ArrayBuffer; - macKey?: ArrayBuffer; - - constructor(key: ArrayBuffer) { - this.key = key; - } -} diff --git a/src/popup/app/app.js b/src/popup/app/app.js index 7786355176..558540f37c 100644 --- a/src/popup/app/app.js +++ b/src/popup/app/app.js @@ -30,16 +30,6 @@ import GlobalModule from './global/global.module'; import SettingsModule from './settings/settings.module'; // Model imports -import { Attachment } from '../../models/domain/attachment'; -import { Card } from '../../models/domain/card'; -import { Cipher } from '../../models/domain/cipher'; -import { Field } from '../../models/domain/field'; -import { Identity } from '../../models/domain/identity'; -import { Login } from '../../models/domain/login'; -import { SecureNote } from '../../models/domain/secureNote'; - -import { CipherString } from '../../models/domain/cipherString'; - import { Data, Domain, Request, Response } from '@bitwarden/jslib'; angular diff --git a/src/popup/app/tools/password-generator-history.component.ts b/src/popup/app/tools/password-generator-history.component.ts index 0bc4bc1c7d..cd1b8dd0e3 100644 --- a/src/popup/app/tools/password-generator-history.component.ts +++ b/src/popup/app/tools/password-generator-history.component.ts @@ -1,10 +1,10 @@ import * as template from './password-generator-history.component.html'; -import PasswordHistory from '../../../models/domain/passwordHistory'; +import { Domain } from '@bitwarden/jslib'; export class PasswordGeneratorHistoryController { $transition$: any; - history: PasswordHistory[]; + history: Domain.PasswordHistory[]; editState: any; addState: any; i18n: any; diff --git a/src/services/abstractions/crypto.service.ts b/src/services/abstractions/crypto.service.ts index 8d424ec784..cb321b676e 100644 --- a/src/services/abstractions/crypto.service.ts +++ b/src/services/abstractions/crypto.service.ts @@ -1,28 +1,27 @@ -import { CipherString } from '../../models/domain/cipherString'; -import SymmetricCryptoKey from '../../models/domain/symmetricCryptoKey'; - -import { Response } from '@bitwarden/jslib'; +import { Domain, Response } from '@bitwarden/jslib'; export interface CryptoService { - setKey(key: SymmetricCryptoKey): Promise; + setKey(key: Domain.SymmetricCryptoKey): Promise; setKeyHash(keyHash: string): Promise<{}>; setEncKey(encKey: string): Promise<{}>; setEncPrivateKey(encPrivateKey: string): Promise<{}>; setOrgKeys(orgs: Response.ProfileOrganization[]): Promise<{}>; - getKey(): Promise; + getKey(): Promise; getKeyHash(): Promise; - getEncKey(): Promise; + getEncKey(): Promise; getPrivateKey(): Promise; - getOrgKeys(): Promise>; - getOrgKey(orgId: string): Promise; + getOrgKeys(): Promise>; + getOrgKey(orgId: string): Promise; clearKeys(): Promise; toggleKey(): Promise; - makeKey(password: string, salt: string): SymmetricCryptoKey; - hashPassword(password: string, key: SymmetricCryptoKey): Promise; - makeEncKey(key: SymmetricCryptoKey): Promise; - encrypt(plainValue: string | Uint8Array, key?: SymmetricCryptoKey, plainValueEncoding?: string): Promise; - encryptToBytes(plainValue: ArrayBuffer, key?: SymmetricCryptoKey): Promise; - decrypt(cipherString: CipherString, key?: SymmetricCryptoKey, outputEncoding?: string): Promise; - decryptFromBytes(encBuf: ArrayBuffer, key: SymmetricCryptoKey): Promise; + makeKey(password: string, salt: string): Domain.SymmetricCryptoKey; + hashPassword(password: string, key: Domain.SymmetricCryptoKey): Promise; + makeEncKey(key: Domain.SymmetricCryptoKey): Promise; + encrypt(plainValue: string | Uint8Array, key?: Domain.SymmetricCryptoKey, + plainValueEncoding?: string): Promise; + encryptToBytes(plainValue: ArrayBuffer, key?: Domain.SymmetricCryptoKey): Promise; + decrypt(cipherString: Domain.CipherString, key?: Domain.SymmetricCryptoKey, + outputEncoding?: string): Promise; + decryptFromBytes(encBuf: ArrayBuffer, key: Domain.SymmetricCryptoKey): Promise; rsaDecrypt(encValue: string): Promise; } diff --git a/src/services/api.service.ts b/src/services/api.service.ts index 39b7c9572b..43c5efc3cd 100644 --- a/src/services/api.service.ts +++ b/src/services/api.service.ts @@ -2,9 +2,7 @@ import AppIdService from './appId.service'; import ConstantsService from './constants.service'; import TokenService from './token.service'; -import { Abstractions, Request as Req, Response as Res } from '@bitwarden/jslib'; - -import EnvironmentUrls from '../models/domain/environmentUrls'; +import { Abstractions, Domain, Request as Req, Response as Res } from '@bitwarden/jslib'; export default class ApiService { urlsSet: boolean = false; @@ -19,7 +17,7 @@ export default class ApiService { this.deviceType = platformUtilsService.getDevice().toString(); } - setUrls(urls: EnvironmentUrls) { + setUrls(urls: Domain.EnvironmentUrls) { this.urlsSet = true; if (urls.base != null) { diff --git a/src/services/cipher.service.ts b/src/services/cipher.service.ts index a8bd777c04..d5ce86dc08 100644 --- a/src/services/cipher.service.ts +++ b/src/services/cipher.service.ts @@ -1,9 +1,4 @@ -import { Abstractions, Data, Enums, Request, Response } from '@bitwarden/jslib'; - -import { Cipher } from '../models/domain/cipher'; -import { CipherString } from '../models/domain/cipherString'; -import { Field } from '../models/domain/field'; -import SymmetricCryptoKey from '../models/domain/symmetricCryptoKey'; +import { Abstractions, Data, Domain, Enums, Request, Response } from '@bitwarden/jslib'; import ApiService from './api.service'; import ConstantsService from './constants.service'; @@ -69,8 +64,8 @@ export default class CipherService { this.decryptedCipherCache = null; } - async encrypt(model: any): Promise { - const cipher = new Cipher(); + async encrypt(model: any): Promise { + const cipher = new Domain.Cipher(); cipher.id = model.id; cipher.folderId = model.folderId; cipher.favorite = model.favorite; @@ -93,17 +88,17 @@ export default class CipherService { return cipher; } - async encryptFields(fieldsModel: any[], key: SymmetricCryptoKey): Promise { + async encryptFields(fieldsModel: any[], key: Domain.SymmetricCryptoKey): Promise { if (!fieldsModel || !fieldsModel.length) { return null; } const self = this; - const encFields: Field[] = []; + const encFields: Domain.Field[] = []; await fieldsModel.reduce((promise, field) => { return promise.then(() => { return self.encryptField(field, key); - }).then((encField: Field) => { + }).then((encField: Domain.Field) => { encFields.push(encField); }); }, Promise.resolve()); @@ -111,8 +106,8 @@ export default class CipherService { return encFields; } - async encryptField(fieldModel: any, key: SymmetricCryptoKey): Promise { - const field = new Field(); + async encryptField(fieldModel: any, key: Domain.SymmetricCryptoKey): Promise { + const field = new Domain.Field(); field.type = fieldModel.type; await this.encryptObjProperty(fieldModel, field, { @@ -123,7 +118,7 @@ export default class CipherService { return field; } - async get(id: string): Promise { + async get(id: string): Promise { const userId = await this.userService.getUserId(); const localData = await this.storageService.get(Keys.localData); const ciphers = await this.storageService.get<{ [id: string]: Data.Cipher; }>( @@ -132,18 +127,18 @@ export default class CipherService { return null; } - return new Cipher(ciphers[id], false, localData ? localData[id] : null); + return new Domain.Cipher(ciphers[id], false, localData ? localData[id] : null); } - async getAll(): Promise { + async getAll(): Promise { const userId = await this.userService.getUserId(); const localData = await this.storageService.get(Keys.localData); const ciphers = await this.storageService.get<{ [id: string]: Data.Cipher; }>( Keys.ciphersPrefix + userId); - const response: Cipher[] = []; + const response: Domain.Cipher[] = []; for (const id in ciphers) { if (ciphers.hasOwnProperty(id)) { - response.push(new Cipher(ciphers[id], false, localData ? localData[id] : null)); + response.push(new Domain.Cipher(ciphers[id], false, localData ? localData[id] : null)); } } return response; @@ -278,7 +273,7 @@ export default class CipherService { await this.storageService.save(Keys.neverDomains, domains); } - async saveWithServer(cipher: Cipher): Promise { + async saveWithServer(cipher: Domain.Cipher): Promise { const request = new Request.Cipher(cipher); let response: Response.Cipher; @@ -294,7 +289,7 @@ export default class CipherService { await this.upsert(data); } - saveAttachmentWithServer(cipher: Cipher, unencryptedFile: any): Promise { + saveAttachmentWithServer(cipher: Domain.Cipher, unencryptedFile: any): Promise { const self = this; return new Promise((resolve, reject) => { @@ -321,7 +316,7 @@ export default class CipherService { const userId = await self.userService.getUserId(); const data = new Data.Cipher(response, userId, cipher.collectionIds); this.upsert(data); - resolve(new Cipher(data)); + resolve(new Domain.Cipher(data)); }; @@ -427,7 +422,7 @@ export default class CipherService { // Helpers - private encryptObjProperty(model: any, obj: any, map: any, key: SymmetricCryptoKey): Promise { + private encryptObjProperty(model: any, obj: any, map: any, key: Domain.SymmetricCryptoKey): Promise { const promises = []; const self = this; @@ -444,7 +439,7 @@ export default class CipherService { return self.cryptoService.encrypt(modelProp, key); } return null; - }).then((val: CipherString) => { + }).then((val: Domain.CipherString) => { theObj[theProp] = val; }); promises.push(p); @@ -454,7 +449,7 @@ export default class CipherService { return Promise.all(promises); } - private encryptCipherData(cipher: Cipher, model: any, key: SymmetricCryptoKey): Promise { + private encryptCipherData(cipher: Domain.Cipher, model: any, key: Domain.SymmetricCryptoKey): Promise { switch (cipher.type) { case Enums.CipherType.Login: model.login = {}; diff --git a/src/services/collection.service.ts b/src/services/collection.service.ts index 5606ef4729..e98851cf1a 100644 --- a/src/services/collection.service.ts +++ b/src/services/collection.service.ts @@ -1,10 +1,7 @@ -import { CipherString } from '../models/domain/cipherString'; -import { Collection } from '../models/domain/collection'; - import CryptoService from './crypto.service'; import UserService from './user.service'; -import { Abstractions, Data } from '@bitwarden/jslib'; +import { Abstractions, Data, Domain } from '@bitwarden/jslib'; const Keys = { collectionsPrefix: 'collections_', @@ -21,7 +18,7 @@ export default class CollectionService { this.decryptedCollectionCache = null; } - async get(id: string): Promise { + async get(id: string): Promise { const userId = await this.userService.getUserId(); const collections = await this.storageService.get<{ [id: string]: Data.Collection; }>( Keys.collectionsPrefix + userId); @@ -29,17 +26,17 @@ export default class CollectionService { return null; } - return new Collection(collections[id]); + return new Domain.Collection(collections[id]); } - async getAll(): Promise { + async getAll(): Promise { const userId = await this.userService.getUserId(); const collections = await this.storageService.get<{ [id: string]: Data.Collection; }>( Keys.collectionsPrefix + userId); - const response: Collection[] = []; + const response: Domain.Collection[] = []; for (const id in collections) { if (collections.hasOwnProperty(id)) { - response.push(new Collection(collections[id])); + response.push(new Domain.Collection(collections[id])); } } return response; diff --git a/src/services/crypto.service.ts b/src/services/crypto.service.ts index 62dafa5621..893dc6bbac 100644 --- a/src/services/crypto.service.ts +++ b/src/services/crypto.service.ts @@ -1,10 +1,6 @@ import * as forge from 'node-forge'; -import { Abstractions, Enums, Response, Services } from '@bitwarden/jslib'; - -import { CipherString } from '../models/domain/cipherString'; -import EncryptedObject from '../models/domain/encryptedObject'; -import SymmetricCryptoKey from '../models/domain/symmetricCryptoKey'; +import { Abstractions, Domain, Enums, Response, Services } from '@bitwarden/jslib'; import ConstantsService from './constants.service'; @@ -31,18 +27,18 @@ const Crypto = window.crypto; const Subtle = Crypto.subtle; export default class CryptoService implements CryptoServiceInterface { - private key: SymmetricCryptoKey; - private encKey: SymmetricCryptoKey; - private legacyEtmKey: SymmetricCryptoKey; + private key: Domain.SymmetricCryptoKey; + private encKey: Domain.SymmetricCryptoKey; + private legacyEtmKey: Domain.SymmetricCryptoKey; private keyHash: string; private privateKey: ArrayBuffer; - private orgKeys: Map; + private orgKeys: Map; constructor(private storageService: Abstractions.StorageService, private secureStorageService: Abstractions.StorageService) { } - async setKey(key: SymmetricCryptoKey): Promise { + async setKey(key: Domain.SymmetricCryptoKey): Promise { this.key = key; const option = await this.storageService.get(ConstantsService.lockOptionKey); @@ -85,7 +81,7 @@ export default class CryptoService implements CryptoServiceInterface { return this.storageService.save(Keys.encOrgKeys, orgKeys); } - async getKey(): Promise { + async getKey(): Promise { if (this.key != null) { return this.key; } @@ -97,7 +93,7 @@ export default class CryptoService implements CryptoServiceInterface { const key = await this.secureStorageService.get(Keys.key); if (key) { - this.key = new SymmetricCryptoKey(key, true); + this.key = new Domain.SymmetricCryptoKey(key, true); } return key == null ? null : this.key; @@ -111,7 +107,7 @@ export default class CryptoService implements CryptoServiceInterface { return this.storageService.get(Keys.keyHash); } - async getEncKey(): Promise { + async getEncKey(): Promise { if (this.encKey != null) { return this.encKey; } @@ -126,12 +122,12 @@ export default class CryptoService implements CryptoServiceInterface { return null; } - const decEncKey = await this.decrypt(new CipherString(encKey), key, 'raw'); + const decEncKey = await this.decrypt(new Domain.CipherString(encKey), key, 'raw'); if (decEncKey == null) { return null; } - this.encKey = new SymmetricCryptoKey(decEncKey); + this.encKey = new Domain.SymmetricCryptoKey(decEncKey); return this.encKey; } @@ -145,13 +141,13 @@ export default class CryptoService implements CryptoServiceInterface { return null; } - const privateKey = await this.decrypt(new CipherString(encPrivateKey), null, 'raw'); + const privateKey = await this.decrypt(new Domain.CipherString(encPrivateKey), null, 'raw'); const privateKeyB64 = forge.util.encode64(privateKey); this.privateKey = Services.UtilsService.fromB64ToArray(privateKeyB64).buffer; return this.privateKey; } - async getOrgKeys(): Promise> { + async getOrgKeys(): Promise> { if (this.orgKeys != null && this.orgKeys.size > 0) { return this.orgKeys; } @@ -162,7 +158,7 @@ export default class CryptoService implements CryptoServiceInterface { return null; } - const orgKeys: Map = new Map(); + const orgKeys: Map = new Map(); let setKey = false; for (const orgId in encOrgKeys) { @@ -171,7 +167,7 @@ export default class CryptoService implements CryptoServiceInterface { } const decValueB64 = await this.rsaDecrypt(encOrgKeys[orgId]); - orgKeys.set(orgId, new SymmetricCryptoKey(decValueB64, true)); + orgKeys.set(orgId, new Domain.SymmetricCryptoKey(decValueB64, true)); setKey = true; } @@ -182,7 +178,7 @@ export default class CryptoService implements CryptoServiceInterface { return this.orgKeys; } - async getOrgKey(orgId: string): Promise { + async getOrgKey(orgId: string): Promise { if (orgId == null) { return null; } @@ -252,13 +248,13 @@ export default class CryptoService implements CryptoServiceInterface { await this.setKey(key); } - makeKey(password: string, salt: string): SymmetricCryptoKey { + makeKey(password: string, salt: string): Domain.SymmetricCryptoKey { const keyBytes: string = (forge as any).pbkdf2(forge.util.encodeUtf8(password), forge.util.encodeUtf8(salt), 5000, 256 / 8, 'sha256'); - return new SymmetricCryptoKey(keyBytes); + return new Domain.SymmetricCryptoKey(keyBytes); } - async hashPassword(password: string, key: SymmetricCryptoKey): Promise { + async hashPassword(password: string, key: Domain.SymmetricCryptoKey): Promise { const storedKey = await this.getKey(); key = key || storedKey; if (!password || !key) { @@ -269,14 +265,14 @@ export default class CryptoService implements CryptoServiceInterface { return forge.util.encode64(hashBits); } - makeEncKey(key: SymmetricCryptoKey): Promise { + makeEncKey(key: Domain.SymmetricCryptoKey): Promise { const bytes = new Uint8Array(512 / 8); Crypto.getRandomValues(bytes); return this.encrypt(bytes, key, 'raw'); } - async encrypt(plainValue: string | Uint8Array, key?: SymmetricCryptoKey, - plainValueEncoding: string = 'utf8'): Promise { + async encrypt(plainValue: string | Uint8Array, key?: Domain.SymmetricCryptoKey, + plainValueEncoding: string = 'utf8'): Promise { if (!plainValue) { return Promise.resolve(null); } @@ -292,10 +288,10 @@ export default class CryptoService implements CryptoServiceInterface { const iv = Services.UtilsService.fromBufferToB64(encValue.iv.buffer); const ct = Services.UtilsService.fromBufferToB64(encValue.ct.buffer); const mac = encValue.mac ? Services.UtilsService.fromBufferToB64(encValue.mac.buffer) : null; - return new CipherString(encValue.key.encType, iv, ct, mac); + return new Domain.CipherString(encValue.key.encType, iv, ct, mac); } - async encryptToBytes(plainValue: ArrayBuffer, key?: SymmetricCryptoKey): Promise { + async encryptToBytes(plainValue: ArrayBuffer, key?: Domain.SymmetricCryptoKey): Promise { const encValue = await this.aesEncrypt(plainValue, key); let macLen = 0; if (encValue.mac) { @@ -313,7 +309,7 @@ export default class CryptoService implements CryptoServiceInterface { return encBytes.buffer; } - async decrypt(cipherString: CipherString, key?: SymmetricCryptoKey, + async decrypt(cipherString: Domain.CipherString, key?: Domain.SymmetricCryptoKey, outputEncoding: string = 'utf8'): Promise { const ivBytes: string = forge.util.decode64(cipherString.initializationVector); const ctBytes: string = forge.util.decode64(cipherString.cipherText); @@ -330,7 +326,7 @@ export default class CryptoService implements CryptoServiceInterface { } } - async decryptFromBytes(encBuf: ArrayBuffer, key: SymmetricCryptoKey): Promise { + async decryptFromBytes(encBuf: ArrayBuffer, key: Domain.SymmetricCryptoKey): Promise { if (!encBuf) { throw new Error('no encBuf.'); } @@ -448,8 +444,8 @@ export default class CryptoService implements CryptoServiceInterface { // Helpers - private async aesEncrypt(plainValue: ArrayBuffer, key: SymmetricCryptoKey): Promise { - const obj = new EncryptedObject(); + private async aesEncrypt(plainValue: ArrayBuffer, key: Domain.SymmetricCryptoKey): Promise { + const obj = new Domain.EncryptedObject(); obj.key = await this.getKeyForEncryption(key); const keyBuf = obj.key.getBuffers(); @@ -472,7 +468,7 @@ export default class CryptoService implements CryptoServiceInterface { } private async aesDecrypt(encType: Enums.EncryptionType, ctBytes: string, ivBytes: string, macBytes: string, - key: SymmetricCryptoKey): Promise { + key: Domain.SymmetricCryptoKey): Promise { const keyForEnc = await this.getKeyForEncryption(key); const theKey = this.resolveLegacyKey(encType, keyForEnc); @@ -501,7 +497,7 @@ export default class CryptoService implements CryptoServiceInterface { } private async aesDecryptWC(encType: Enums.EncryptionType, ctBuf: ArrayBuffer, ivBuf: ArrayBuffer, - macBuf: ArrayBuffer, key: SymmetricCryptoKey): Promise { + macBuf: ArrayBuffer, key: Domain.SymmetricCryptoKey): Promise { const theKey = await this.getKeyForEncryption(key); const keyBuf = theKey.getBuffers(); const encKey = await Subtle.importKey('raw', keyBuf.encKey, AesAlgorithm, false, ['decrypt']); @@ -577,7 +573,7 @@ export default class CryptoService implements CryptoServiceInterface { return true; } - private async getKeyForEncryption(key?: SymmetricCryptoKey): Promise { + private async getKeyForEncryption(key?: Domain.SymmetricCryptoKey): Promise { if (key) { return key; } @@ -586,12 +582,12 @@ export default class CryptoService implements CryptoServiceInterface { return encKey || (await this.getKey()); } - private resolveLegacyKey(encType: Enums.EncryptionType, key: SymmetricCryptoKey): SymmetricCryptoKey { + private resolveLegacyKey(encType: Enums.EncryptionType, key: Domain.SymmetricCryptoKey): Domain.SymmetricCryptoKey { if (encType === Enums.EncryptionType.AesCbc128_HmacSha256_B64 && key.encType === Enums.EncryptionType.AesCbc256_B64) { // Old encrypt-then-mac scheme, make a new key this.legacyEtmKey = this.legacyEtmKey || - new SymmetricCryptoKey(key.key, false, Enums.EncryptionType.AesCbc128_HmacSha256_B64); + new Domain.SymmetricCryptoKey(key.key, false, Enums.EncryptionType.AesCbc128_HmacSha256_B64); return this.legacyEtmKey; } diff --git a/src/services/environment.service.ts b/src/services/environment.service.ts index fcacfb8f0f..d143713f64 100644 --- a/src/services/environment.service.ts +++ b/src/services/environment.service.ts @@ -1,9 +1,7 @@ import ApiService from './api.service'; import ConstantsService from './constants.service'; -import { Abstractions } from '@bitwarden/jslib'; - -import EnvironmentUrls from '../models/domain/environmentUrls'; +import { Abstractions, Domain } from '@bitwarden/jslib'; export default class EnvironmentService { baseUrl: string; @@ -25,7 +23,7 @@ export default class EnvironmentService { webVault: null, }; - const envUrls = new EnvironmentUrls(); + const envUrls = new Domain.EnvironmentUrls(); if (urls.base) { this.baseUrl = envUrls.base = urls.base; @@ -61,7 +59,7 @@ export default class EnvironmentService { this.identityUrl = urls.identity; this.iconsUrl = urls.icons; - const envUrls = new EnvironmentUrls(); + const envUrls = new Domain.EnvironmentUrls(); if (this.baseUrl) { envUrls.base = this.baseUrl; } else { diff --git a/src/services/folder.service.ts b/src/services/folder.service.ts index 66d4e58054..687e6ed339 100644 --- a/src/services/folder.service.ts +++ b/src/services/folder.service.ts @@ -1,5 +1,3 @@ -import { CipherString } from '../models/domain/cipherString'; - import ApiService from './api.service'; import CryptoService from './crypto.service'; import UserService from './user.service'; diff --git a/src/services/passwordGeneration.service.ts b/src/services/passwordGeneration.service.ts index 82536900ae..e953aa0e72 100644 --- a/src/services/passwordGeneration.service.ts +++ b/src/services/passwordGeneration.service.ts @@ -1,9 +1,6 @@ -import { CipherString } from '../models/domain/cipherString'; -import PasswordHistory from '../models/domain/passwordHistory'; - import CryptoService from './crypto.service'; -import { Abstractions, Services } from '@bitwarden/jslib'; +import { Abstractions, Domain, Services } from '@bitwarden/jslib'; const DefaultOptions = { length: 14, @@ -144,10 +141,10 @@ export default class PasswordGenerationService { } optionsCache: any; - history: PasswordHistory[] = []; + history: Domain.PasswordHistory[] = []; constructor(private cryptoService: CryptoService, private storageService: Abstractions.StorageService) { - storageService.get(Keys.history).then((encrypted) => { + storageService.get(Keys.history).then((encrypted) => { return this.decryptHistory(encrypted); }).then((history) => { this.history = history; @@ -177,7 +174,7 @@ export default class PasswordGenerationService { } getHistory() { - return this.history || new Array(); + return this.history || new Array(); } async addHistory(password: string): Promise { @@ -186,7 +183,7 @@ export default class PasswordGenerationService { return; } - this.history.push(new PasswordHistory(password, Date.now())); + this.history.push(new Domain.PasswordHistory(password, Date.now())); // Remove old items. if (this.history.length > MaxPasswordsInHistory) { @@ -202,27 +199,27 @@ export default class PasswordGenerationService { return await this.storageService.remove(Keys.history); } - private async encryptHistory(): Promise { + private async encryptHistory(): Promise { if (this.history == null || this.history.length === 0) { return Promise.resolve([]); } const promises = this.history.map(async (item) => { const encrypted = await this.cryptoService.encrypt(item.password); - return new PasswordHistory(encrypted.encryptedString, item.date); + return new Domain.PasswordHistory(encrypted.encryptedString, item.date); }); return await Promise.all(promises); } - private async decryptHistory(history: PasswordHistory[]): Promise { + private async decryptHistory(history: Domain.PasswordHistory[]): Promise { if (history == null || history.length === 0) { return Promise.resolve([]); } const promises = history.map(async (item) => { - const decrypted = await this.cryptoService.decrypt(new CipherString(item.password)); - return new PasswordHistory(decrypted, item.date); + const decrypted = await this.cryptoService.decrypt(new Domain.CipherString(item.password)); + return new Domain.PasswordHistory(decrypted, item.date); }); return await Promise.all(promises);