Fix issues with encrypted object creation

Signed-off-by: Marius David Wieschollek's avatarMarius David Wieschollek <passwords.public@mdns.eu>
parent 39f832d0
......@@ -63,6 +63,7 @@ import ChallengeTypeNotSupported from "../Exception/ChallengeTypeNotSupported";
import ConfigurationError from "../Exception/ConfigruationError";
import MissingEncryptionKeyError from "../Exception/Encryption/MissingEncryptionKeyError";
import InvalidEncryptedTextLength from "../Exception/Encryption/InvalidEncryptedTextLength";
import HashService from "../Services/HashService";
export default class DefaultClassLoader extends BasicClassLoader {
......@@ -119,6 +120,7 @@ export default class DefaultClassLoader extends BasicClassLoader {
'keychain.csev1': (k, p) => { return new CSEv1Keychain(this.getInstance('classes'), k, p); },
'service.hash' : () => { return new HashService(this.getInstance('classes')); },
'service.model' : () => { return new ModelService(this.getInstance('classes')); },
'service.password': () => { return new PasswordService(this.getInstance('client')); },
......
......@@ -138,7 +138,7 @@ export default class AbstractCollection {
}
/**
* @return {String[]}
* @return {Object}
*/
toJSON() {
let json = [];
......@@ -147,7 +147,7 @@ export default class AbstractCollection {
json.push(this._converter.toObject(element));
}
return JSON.stringify(json);
return json;
}
[Symbol.iterator]() {
......
......@@ -89,7 +89,7 @@ export default class AbstractConverter {
* @api
*/
async toEncryptedData(model) {
let data = this.toObject(model);
let data = await this.toObject(model);
if(data.cseType === 'none') {
return await this._api.getInstance('encryption.none').encrypt(data, this._type);
......
......@@ -8,8 +8,9 @@ export default class PasswordConverter extends AbstractConverter {
*/
constructor(api) {
super(api, 'password');
/** @type CustomFieldConverter **/
/** @type {CustomFieldConverter} **/
this._customFieldConverter = this._api.getInstance('converter.field');
this._hashService = /** @type {HashService} **/ this._api.getInstance('service.hash');
}
/**
......@@ -37,4 +38,18 @@ export default class PasswordConverter extends AbstractConverter {
return this._api.getClass(`model.${this._type}`, clone, this._api);
}
/**
*
* @param {(Password|AbstractRevisionModel)} model
* @returns {Promise<void>}
*/
async toObject(model) {
let data = super.toObject(model);
data.customFields = this._customFieldConverter.toJSON(model.getCustomFields());
data.hash = await this._hashService.getHash(model.getPassword(), this._hashService.HASH_SHA_1);
return data;
}
}
\ No newline at end of file
......@@ -49,11 +49,10 @@ export default class CSEv1Encryption {
let fields = this.fields[type],
key = this._keychain.getCurrentKey();
for(let i = 0; i < fields.length; i++) {
let field = fields[i],
data = object[field];
for(let field of fields) {
let data = object[field];
if(data === null || data.length === 0) continue;
if(data === null || data === undefined || data.length === 0) continue;
object[field] = this._encryptString(data, key);
}
......@@ -78,9 +77,8 @@ export default class CSEv1Encryption {
let fields = this.fields[type],
key = this._keychain.getKey(object.cseKey);
for(let i = 0; i < fields.length; i++) {
let field = fields[i],
data = object[field];
for(let field of fields) {
let data = object[field];
if(data === null || data.length === 0) continue;
object[field] = this._decryptString(data, key);
......
import sodium from "libsodium-wrappers";
export default class HashService {
get HASH_SHA_1() {
return 'SHA-1';
}
get HASH_SHA_256() {
return 'SHA-256';
}
get HASH_SHA_384() {
return 'SHA-384';
}
get HASH_SHA_512() {
return 'SHA-512';
}
get HASH_BLAKE2B() {
return 'BLAKE2b';
}
get HASH_BLAKE2B_224() {
return 'BLAKE2b-224';
}
get HASH_BLAKE2B_256() {
return 'BLAKE2b-256';
}
get HASH_BLAKE2B_384() {
return 'BLAKE2b-384';
}
get HASH_BLAKE2B_512() {
return 'BLAKE2b-512';
}
get HASH_ARGON2() {
return 'Argon2';
}
constructor(classLoader) {
this._ready = classLoader.getClass('state.boolean', false);
sodium.ready.then(() => {this._ready.set(true);});
}
/**
* Generate a hash of the given value with the given algorithm
*
* @param {String} value
* @param {String} [algorithm=SHA-1]
* @returns {Promise<string>}
*/
async getHash(value, algorithm = 'SHA-1') {
await this._ready.awaitTrue();
if([this.HASH_SHA_1, this.HASH_SHA_256, this.HASH_SHA_384, this.HASH_SHA_512].indexOf(algorithm) !== -1) {
return await this._makeShaHash(value, algorithm);
} else if(algorithm.substr(0, 7) === this.HASH_BLAKE2B) {
return this._makeBlake2bHash(algorithm, value);
} else if(algorithm === this.HASH_ARGON2) {
return sodium.crypto_pwhash_str(value, sodium.crypto_pwhash_OPSLIMIT_MIN, sodium.crypto_pwhash_MEMLIMIT_MIN);
}
}
/**
*
* @param {String} value
* @param {String} algorithm
* @returns {Promise<String>}
* @private
*/
async _makeShaHash(value, algorithm) {
let msgBuffer = new TextEncoder('utf-8').encode(value),
hashBuffer = await crypto.subtle.digest(algorithm, msgBuffer);
return sodium.to_hex(new Uint8Array(hashBuffer));
}
/**
* @param {String} algorithm
* @param {String} value
* @returns {String}
* @private
*/
_makeBlake2bHash(algorithm, value) {
let bytes = sodium.crypto_generichash_BYTES_MAX;
if(algorithm.indexOf('-') !== -1) {
bytes = algorithm.split('-')[1];
if(sodium.crypto_generichash_BYTES_MAX < bytes) bytes = sodium.crypto_generichash_BYTES_MAX;
if(sodium.crypto_generichash_BYTES_MIN > bytes) bytes = sodium.crypto_generichash_BYTES_MIN;
}
return sodium.to_hex(sodium.crypto_generichash(bytes, sodium.from_string(value)));
}
}
\ No newline at end of file
......@@ -22,6 +22,7 @@ export default class ModelService {
addModel(type, model) {
this._cache.set(`${type}.${model.getId()}`, model);
this._cache.set(`${type}.${model.getId()}.${model.getRevision()}`, model);
// @TODO update related models
}
......@@ -254,7 +255,6 @@ export default class ModelService {
_mergeStandardProperties(model, newModel, excludeProperties) {
if(model.getRevision() === newModel.getRevision()) {
model.setUpdated(newModel.getUpdated());
return;
}
excludeProperties.push('id, revisions')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment