1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-11 13:53:34 +00:00
Files
browser/src/models/domainModels.js
Kyle Spearrin c26976e865 fixes
2017-10-21 13:11:47 -04:00

469 lines
14 KiB
JavaScript

var CipherString = function () {
this.encryptedString = null;
this.encryptionType = null;
this.decryptedValue = null;
this.cipherText = null;
this.initializationVector = null;
this.mac = null;
this.cryptoService = chrome.extension.getBackgroundPage().bg_cryptoService;
var constants = chrome.extension.getBackgroundPage().bg_constantsService;
if (arguments.length >= 2) {
// ct and header
this.encryptedString = arguments[0] + '.' + arguments[1];
// iv
if (arguments.length > 2 && arguments[2]) {
this.encryptedString += ('|' + arguments[2]);
}
// mac
if (arguments.length > 3 && arguments[3]) {
this.encryptedString += ('|' + arguments[3]);
}
this.encryptionType = arguments[0];
this.cipherText = arguments[1];
this.initializationVector = arguments[2] || null;
this.mac = arguments[3] || null;
return;
}
else if (arguments.length !== 1) {
return;
}
this.encryptedString = arguments[0];
if (!this.encryptedString) {
return;
}
var headerPieces = this.encryptedString.split('.'),
encPieces;
if (headerPieces.length === 2) {
try {
this.encryptionType = parseInt(headerPieces[0]);
encPieces = headerPieces[1].split('|');
}
catch (e) {
return;
}
}
else {
encPieces = this.encryptedString.split('|');
this.encryptionType = encPieces.length === 3 ? constants.encType.AesCbc128_HmacSha256_B64 :
constants.encType.AesCbc256_B64;
}
switch (this.encryptionType) {
case constants.encType.AesCbc128_HmacSha256_B64:
case constants.encType.AesCbc256_HmacSha256_B64:
if (encPieces.length !== 3) {
return;
}
this.initializationVector = encPieces[0];
this.cipherText = encPieces[1];
this.mac = encPieces[2];
break;
case constants.encType.AesCbc256_B64:
if (encPieces.length !== 2) {
return;
}
this.initializationVector = encPieces[0];
this.cipherText = encPieces[1];
break;
case constants.encType.Rsa2048_OaepSha256_B64:
case constants.encType.Rsa2048_OaepSha1_B64:
if (encPieces.length !== 1) {
return;
}
this.cipherText = encPieces[0];
break;
default:
return;
}
};
var Cipher = function (obj, alreadyEncrypted, localData) {
this.constantsService = chrome.extension.getBackgroundPage().bg_constantsService;
this.utilsService = chrome.extension.getBackgroundPage().bg_utilsService;
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 ? true : false;
this.organizationUseTotp = obj.organizationUseTotp ? true : false;
this.edit = obj.edit ? true : false;
this.localData = localData;
switch (this.type) {
case this.constantsService.cipherType.login:
this.login = new Login2(obj.login, alreadyEncrypted);
break;
case this.constantsService.cipherType.secureNote:
this.secureNote = new SecureNote(obj.secureNote, alreadyEncrypted);
break;
case this.constantsService.cipherType.card:
this.card = new Card(obj.card, alreadyEncrypted);
break;
case this.constantsService.cipherType.identity:
this.identity = new Identity(obj.identity, alreadyEncrypted);
break;
default:
break;
}
var i;
if (obj.attachments) {
this.attachments = [];
for (i = 0; i < obj.attachments.length; i++) {
this.attachments.push(new Attachment(obj.attachments[i], alreadyEncrypted));
}
}
else {
this.attachments = null;
}
if (obj.fields) {
this.fields = [];
for (i = 0; i < obj.fields.length; i++) {
this.fields.push(new Field(obj.fields[i], alreadyEncrypted));
}
}
else {
this.fields = null;
}
};
var Login2 = function (obj, alreadyEncrypted) {
buildDomainModel(this, obj, {
uri: null,
username: null,
password: null,
totp: null
}, alreadyEncrypted, []);
};
var Identity = function (obj, alreadyEncrypted) {
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, []);
};
var Card = function (obj, alreadyEncrypted) {
buildDomainModel(this, obj, {
cardholderName: null,
brand: null,
number: null,
expMonth: null,
expYear: null,
code: null
}, alreadyEncrypted, []);
};
var SecureNote = function (obj, alreadyEncrypted) {
this.type = obj.type;
};
var Field = function (obj, alreadyEncrypted) {
this.type = obj.type;
buildDomainModel(this, obj, {
name: null,
value: null
}, alreadyEncrypted, []);
};
var Attachment = function (obj, alreadyEncrypted) {
this.size = obj.size;
buildDomainModel(this, obj, {
id: null,
url: null,
sizeName: null,
fileName: null
}, alreadyEncrypted, ['id', 'url', 'sizeName']);
};
var Folder = function (obj, alreadyEncrypted) {
buildDomainModel(this, obj, {
id: null,
name: null
}, alreadyEncrypted, ['id']);
};
function buildDomainModel(model, obj, map, alreadyEncrypted, notEncList) {
notEncList = notEncList || [];
for (var prop in map) {
if (map.hasOwnProperty(prop)) {
var 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;
}
}
}
}
(function () {
CipherString.prototype.decrypt = function (orgId) {
if (this.decryptedValue) {
return Q(this.decryptedValue);
}
var self = this;
return self.cryptoService.getOrgKey(orgId).then(function (orgKey) {
return self.cryptoService.decrypt(self, orgKey);
}).then(function (decValue) {
self.decryptedValue = decValue;
return self.decryptedValue;
}).catch(function () {
self.decryptedValue = '[error: cannot decrypt]';
return self.decryptedValue;
});
};
Cipher.prototype.decrypt = function () {
var self = this;
var model = {
id: self.id,
organizationId: self.organizationId,
folderId: self.folderId,
favorite: self.favorite,
type: self.type,
localData: self.localData
};
var attachments = [];
var fields = [];
return decryptObj(model, this, {
name: null,
notes: null
}, self.organizationId).then(function () {
switch (self.type) {
case self.constantsService.cipherType.login:
return self.login.decrypt(self.organizationId);
case self.constantsService.cipherType.secureNote:
return self.secureNote.decrypt(self.organizationId);
case self.constantsService.cipherType.card:
return self.card.decrypt(self.organizationId);
case self.constantsService.cipherType.identity:
return self.identity.decrypt(self.organizationId);
default:
return;
}
}).then(function (decObj) {
switch (self.type) {
case self.constantsService.cipherType.login:
model.login = decObj;
model.subTitle = model.login.username;
if (model.login.uri) {
model.login.domain = self.utilsService.getDomain(model.login.uri);
}
break;
case self.constantsService.cipherType.secureNote:
model.secureNote = decObj;
model.subTitle = null;
break;
case self.constantsService.cipherType.card:
model.card = decObj;
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 self.constantsService.cipherType.identity:
model.identity = decObj;
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;
}
return;
}).then(function () {
if (self.attachments) {
return self.attachments.reduce(function (promise, attachment) {
return promise.then(function () {
return attachment.decrypt(self.organizationId);
}).then(function (decAttachment) {
attachments.push(decAttachment);
});
}, Q());
}
return;
}).then(function () {
model.attachments = attachments.length ? attachments : null;
if (self.fields) {
return self.fields.reduce(function (promise, field) {
return promise.then(function () {
return field.decrypt(self.organizationId);
}).then(function (decField) {
fields.push(decField);
});
}, Q());
}
return;
}).then(function () {
model.fields = fields.length ? fields : null;
return model;
}, function (e) {
console.log(e);
});
};
Login2.prototype.decrypt = function (orgId) {
return decryptObj({}, this, {
uri: null,
username: null,
password: null,
totp: null
}, orgId);
};
Card.prototype.decrypt = function (orgId) {
return decryptObj({}, this, {
cardholderName: null,
brand: null,
number: null,
expMonth: null,
expYear: null,
code: null
}, orgId);
};
SecureNote.prototype.decrypt = function (orgId) {
return {
type: this.type
};
};
Identity.prototype.decrypt = function (orgId) {
return decryptObj({}, this, {
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);
};
Field.prototype.decrypt = function (orgId) {
var model = {
type: this.type
};
return decryptObj(model, this, {
name: null,
value: null
}, orgId);
};
Attachment.prototype.decrypt = function (orgId) {
var model = {
id: this.id,
size: this.size,
sizeName: this.sizeName,
url: this.url
};
return decryptObj(model, this, {
fileName: null
}, orgId);
};
Folder.prototype.decrypt = function () {
var self = this;
var model = {
id: self.id
};
return decryptObj(model, this, {
name: null
}, null);
};
function decryptObj(model, self, map, orgId) {
var promises = [];
for (var prop in map) {
if (map.hasOwnProperty(prop)) {
/* jshint ignore:start */
(function (theProp) {
var promise = Q().then(function () {
var mapProp = map[theProp] || theProp;
if (self[mapProp]) {
return self[mapProp].decrypt(orgId);
}
return null;
}).then(function (val) {
model[theProp] = val;
return;
});
promises.push(promise);
})(prop);
/* jshint ignore:end */
}
}
return Q.all(promises).then(function () {
return model;
});
}
})();