Change blob password

This commit is contained in:
yflory 2019-10-30 18:29:33 +01:00
parent da3df964dd
commit c64eabc33a
5 changed files with 228 additions and 90 deletions

2
rpc.js
View File

@ -857,6 +857,7 @@ var removeOwnedChannel = function (Env, channelId, unsafeKey, cb) {
if (err) { if (err) {
return void cb("E_PROOF_REMOVAL"); return void cb("E_PROOF_REMOVAL");
} }
cb();
}); });
} }
@ -869,6 +870,7 @@ var removeOwnedChannel = function (Env, channelId, unsafeKey, cb) {
if (err) { if (err) {
return void cb("E_PROOF_REMOVAL"); return void cb("E_PROOF_REMOVAL");
} }
cb();
}); });
}); });
} }

View File

@ -79,8 +79,10 @@ define([
waitFor.abort(); waitFor.abort();
return void cb(err || 'EEMPTY'); return void cb(err || 'EEMPTY');
} }
delete val.owners; if (!val.fileType) {
delete val.expire; delete val.owners;
delete val.expire;
}
Util.extend(data, val); Util.extend(data, val);
if (data.href) { data.href = base + data.href; } if (data.href) { data.href = base + data.href; }
if (data.roHref) { data.roHref = base + data.roHref; } if (data.roHref) { data.roHref = base + data.roHref; }
@ -549,11 +551,12 @@ define([
$d.append(password); $d.append(password);
} }
if (!data.noEditPassword && owned && parsed.hashData.type === 'pad' && parsed.type !== "sheet") { // FIXME SHEET fix password change for sheets if (!data.noEditPassword && owned && parsed.type !== "sheet") { // FIXME SHEET fix password change for sheets
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
var changePwTitle = Messages.properties_changePassword; var changePwTitle = Messages.properties_changePassword;
var changePwConfirm = Messages.properties_confirmChange; var changePwConfirm = Messages.properties_confirmChange;
var isSharedFolder = parsed.type === 'drive'; var isSharedFolder = parsed.type === 'drive';
var isFile = parsed.hashData.type === 'file';
if (!hasPassword) { if (!hasPassword) {
changePwTitle = Messages.properties_addPassword; changePwTitle = Messages.properties_addPassword;
changePwConfirm = Messages.properties_confirmNew; changePwConfirm = Messages.properties_confirmNew;
@ -581,7 +584,8 @@ define([
UI.confirm(changePwConfirm, function (yes) { UI.confirm(changePwConfirm, function (yes) {
if (!yes) { pLocked = false; return; } if (!yes) { pLocked = false; return; }
$(passwordOk).html('').append(h('span.fa.fa-spinner.fa-spin', {style: 'margin-left: 0'})); $(passwordOk).html('').append(h('span.fa.fa-spinner.fa-spin', {style: 'margin-left: 0'}));
sframeChan.query("Q_PAD_PASSWORD_CHANGE", { var q = isFile ? 'Q_BLOB_PASSWORD_CHANGE' : 'Q_PAD_PASSWORD_CHANGE';
sframeChan.query(q, {
teamId: typeof(owned) !== "boolean" ? owned : undefined, teamId: typeof(owned) !== "boolean" ? owned : undefined,
href: data.href || data.roHref, href: data.href || data.roHref,
password: newPass password: newPass
@ -593,6 +597,9 @@ define([
return void UI.alert(Messages.properties_passwordError); return void UI.alert(Messages.properties_passwordError);
} }
UI.findOKButton().click(); UI.findOKButton().click();
if (isFile) {
return void UI.alert(Messages.properties_passwordSuccess);
}
// If we didn't have a password, we have to add the /p/ // If we didn't have a password, we have to add the /p/
// If we had a password and we changed it to a new one, we just have to reload // If we had a password and we changed it to a new one, we just have to reload
// If we had a password and we removed it, we have to remove the /p/ // If we had a password and we removed it, we have to remove the /p/

View File

@ -1023,7 +1023,7 @@ define([
}); });
}; };
common.changeBlobPassword = function (Crypt, Crypto, data, cb) { common.changeBlobPassword = function (data, handlers, cb) {
var href = data.href; var href = data.href;
var newPassword = data.password; var newPassword = data.password;
var teamId = data.teamId; var teamId = data.teamId;
@ -1032,26 +1032,34 @@ define([
if (!parsed.hash) { return void cb({ error: 'EINVAL_HREF' }); } if (!parsed.hash) { return void cb({ error: 'EINVAL_HREF' }); }
if (parsed.hashData.type !== 'file') { return void cb({ error: 'EINVAL_TYPE' }); } if (parsed.hashData.type !== 'file') { return void cb({ error: 'EINVAL_TYPE' }); }
var newSecret;
var newHash;
if (parsed.hashData.version >= 2) { if (parsed.hashData.version >= 2) {
newSecret = Hash.getSecrets(parsed.type, parsed.hash, newPassword); newSecret = Hash.getSecrets(parsed.type, parsed.hash, newPassword);
if (!(newSecret.keys && newSecret.keys.editKeyStr)) { if (!(newSecret.keys && newSecret.keys.fileKeyStr)) {
return void cb({error: 'EAUTH'}); return void cb({error: 'EAUTH'});
} }
newHash = Hash.getEditHashFromKeys(newSecret); newHash = Hash.getFileHashFromKeys(newSecret);
} else { } else {
newHash = Hash.createRandomHash(parsed.type, newPassword); newHash = Hash.createRandomHash(parsed.type, newPassword);
newSecret = Hash.getSecrets(parsed.type, newHash, newPassword); newSecret = Hash.getSecrets(parsed.type, newHash, newPassword);
} }
var newHref = '/' + parsed.type + '/#' + newHash; var newHref = '/' + parsed.type + '/#' + newHash;
var fileHost = Config.fileHost || window.location.origin || '';
/* /*
1. get old password 1. get old password
2. get owners 2. get owners
*/ */
var oldPassword; var oldPassword;
var oldSecret; var decrypted;
var oldChannel; var oldChannel;
var oldMetadata; var warning;
var FileCrypto;
var MediaTag;
var Upload;
Nthen(function (waitFor) { Nthen(function (waitFor) {
if (parsed.hashData && parsed.hashData.password) { if (parsed.hashData && parsed.hashData.password) {
common.getPadAttribute('password', waitFor(function (err, password) { common.getPadAttribute('password', waitFor(function (err, password) {
@ -1059,12 +1067,91 @@ define([
}), href); }), href);
} }
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
oldSecret = Hash.getSecrets(parsed.type, parsed.hash, optsGet.password); require([
oldChannel = oldSecret.channel; '/file/file-crypto.js',
common.getPadMetadata({channel: oldChannel}, waitFor(function (metadata) { '/common/media-tag.js',
oldMetadata = metadata; '/common/outer/upload.js',
'/bower_components/tweetnacl/nacl-fast.min.js'
], waitFor(function (_FileCrypto, _MT, _Upload) {
FileCrypto = _FileCrypto;
MediaTag = _MT;
Upload = _Upload;
})); }));
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
var oldSecret = Hash.getSecrets(parsed.type, parsed.hash, oldPassword);
oldChannel = oldSecret.channel;
var src = fileHost + Hash.getBlobPathFromHex(oldChannel);
var key = oldSecret.keys && oldSecret.keys.cryptKey;
var cryptKey = window.nacl.util.encodeBase64(key);
var mt = document.createElement('media-tag');
mt.setAttribute('src', src);
mt.setAttribute('data-crypto-key', 'cryptpad:'+cryptKey);
MediaTag(mt).on('complete', waitFor(function (_decrypted) {
decrypted = _decrypted;
})).on('error', function (err) {
waitFor.abort();
cb({error: err});
console.error(err);
});
}).nThen(function (waitFor) {
var reader = new FileReader();
reader.readAsArrayBuffer(decrypted.content);
reader.onloadend = waitFor(function() {
decrypted.u8 = new Uint8Array(reader.result);
});
}).nThen(function (waitFor) {
var key = newSecret.keys && newSecret.keys.cryptKey;
var onError = function (err) {
waitFor.abort();
cb({error: err});
};
Upload.uploadU8(common, {
teamId: teamId,
u8: decrypted.u8,
metadata: decrypted.metadata,
key: key,
id: newSecret.channel,
owned: true,
onError: onError,
onPending: handlers.onPending,
updateProgress: handlers.updateProgress,
}, waitFor());
}).nThen(function (waitFor) {
// Set the new password to our pad data
common.setPadAttribute('password', newPassword, waitFor(function (err) {
if (err) { warning = true; }
}), href);
common.setPadAttribute('channel', newSecret.channel, waitFor(function (err) {
if (err) { warning = true; }
}), href);
if (parsed.hashData.password && newPassword) { return; } // same hash
common.setPadAttribute('href', newHref, waitFor(function (err) {
if (err) { warning = true; }
}), href);
}).nThen(function (waitFor) {
// delete the old pad
common.removeOwnedChannel({
channel: oldChannel,
teamId: teamId
}, waitFor(function (obj) {
if (obj && obj.error) {
waitFor.abort();
return void cb(obj);
}
}));
postMessage("CHANGE_PAD_PASSWORD_PIN", {
oldChannel: oldChannel,
channel: newSecret.channel
}, waitFor());
}).nThen(function () {
cb({
warning: warning,
hash: newHash,
href: newHref,
});
}); });
}; };

View File

@ -7,6 +7,82 @@ define([
var Nacl = window.nacl; var Nacl = window.nacl;
var module = {}; var module = {};
module.uploadU8 =function (common, data, cb) {
var teamId = data.teamId;
var u8 = data.u8;
var metadata = data.metadata;
var key = data.key;
var onError = data.onError || function () {};
var onPending = data.onPending || function () {};
var updateProgress = data.updateProgress || function () {};
var owned = data.owned;
var id = data.id;
var next = FileCrypto.encrypt(u8, metadata, key);
var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata);
var sendChunk = function (box, cb) {
var enc = Nacl.util.encodeBase64(box);
common.uploadChunk(teamId, enc, function (e, msg) {
cb(e, msg);
});
};
var actual = 0;
var again = function (err, box) {
if (err) { onError(err); }
if (box) {
actual += box.length;
var progressValue = (actual / estimate * 100);
progressValue = Math.min(progressValue, 100);
updateProgress(progressValue);
return void sendChunk(box, function (e) {
if (e) { return console.error(e); }
next(again);
});
}
if (actual !== estimate) {
console.error('Estimated size does not match actual size');
}
// if not box then done
common.uploadComplete(teamId, id, owned, function (e) {
if (e) { return void console.error(e); }
var uri = ['', 'blob', id.slice(0,2), id].join('/');
console.log("encrypted blob is now available as %s", uri);
cb();
});
};
common.uploadStatus(teamId, estimate, function (e, pending) {
if (e) {
console.error(e);
onError(e);
return;
}
if (pending) {
return void onPending(function () {
// if the user wants to cancel the pending upload to execute that one
common.uploadCancel(teamId, estimate, function (e) {
if (e) {
return void console.error(e);
}
next(again);
});
});
}
next(again);
});
};
module.upload = function (file, noStore, common, updateProgress, onComplete, onError, onPending) { module.upload = function (file, noStore, common, updateProgress, onComplete, onError, onPending) {
var u8 = file.blob; // This is not a blob but a uint8array var u8 = file.blob; // This is not a blob but a uint8array
var metadata = file.metadata; var metadata = file.metadata;
@ -50,85 +126,36 @@ define([
metadata.owners = [edPublic]; metadata.owners = [edPublic];
})); }));
}).nThen(function () { }).nThen(function () {
var next = FileCrypto.encrypt(u8, metadata, key); module.uploadU8(common, {
teamId: teamId,
u8: u8,
metadata: metadata,
key: key,
id: id,
owned: owned,
onError: onError,
onPending: onPending,
updateProgress: updateProgress,
}, function () {
if (noStore) { return void onComplete(href); }
var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata); var title = metadata.name;
var data = {
var sendChunk = function (box, cb) { teamId: teamId,
var enc = Nacl.util.encodeBase64(box); title: title || "",
common.uploadChunk(teamId, enc, function (e, msg) { href: href,
cb(e, msg); path: path,
password: password,
channel: id,
owners: metadata.owners,
forceSave: forceSave
};
common.setPadTitle(data, function (err) {
if (err) { return void console.error(err); }
onComplete(href);
common.setPadAttribute('fileType', metadata.type, null, href);
common.setPadAttribute('owners', metadata.owners, null, href);
}); });
};
var actual = 0;
var again = function (err, box) {
if (err) { throw new Error(err); }
if (box) {
actual += box.length;
var progressValue = (actual / estimate * 100);
progressValue = Math.min(progressValue, 100);
updateProgress(progressValue);
return void sendChunk(box, function (e) {
if (e) { return console.error(e); }
next(again);
});
}
if (actual !== estimate) {
console.error('Estimated size does not match actual size');
}
// if not box then done
common.uploadComplete(teamId, id, owned, function (e) {
if (e) { return void console.error(e); }
var uri = ['', 'blob', id.slice(0,2), id].join('/');
console.log("encrypted blob is now available as %s", uri);
var title = metadata.name;
if (noStore) { return void onComplete(href); }
var data = {
teamId: teamId,
title: title || "",
href: href,
path: path,
password: password,
channel: id,
owners: metadata.owners,
forceSave: forceSave
};
common.setPadTitle(data, function (err) {
if (err) { return void console.error(err); }
onComplete(href);
common.setPadAttribute('fileType', metadata.type, null, href);
common.setPadAttribute('owners', metadata.owners, null, href);
});
});
};
common.uploadStatus(teamId, estimate, function (e, pending) {
if (e) {
console.error(e);
onError(e);
return;
}
if (pending) {
return void onPending(function () {
// if the user wants to cancel the pending upload to execute that one
common.uploadCancel(teamId, estimate, function (e) {
if (e) {
return void console.error(e);
}
next(again);
});
});
}
next(again);
}); });
}); });

View File

@ -991,6 +991,21 @@ define([
}); });
}); });
sframeChan.on('Q_BLOB_PASSWORD_CHANGE', function (data, cb) {
data.href = data.href || window.location.href;
var onPending = function () {
// XXX
};
var updateProgress = function (p) {
// XXX
console.log(p);
};
Cryptpad.changeBlobPassword(data, {
onPending: onPending,
updateProgress: updateProgress
}, cb);
});
sframeChan.on('Q_PAD_PASSWORD_CHANGE', function (data, cb) { sframeChan.on('Q_PAD_PASSWORD_CHANGE', function (data, cb) {
data.href = data.href || window.location.href; data.href = data.href || window.location.href;
Cryptpad.changePadPassword(Cryptget, Crypto, data, cb); Cryptpad.changePadPassword(Cryptget, Crypto, data, cb);