Password-protected files: upload files with hashes V2
This commit is contained in:
parent
c7e08fedfb
commit
586193d6a1
65
rpc.js
65
rpc.js
@ -53,9 +53,15 @@ var uint8ArrayToHex = function (a) {
|
|||||||
}).join('');
|
}).join('');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var testFileId = function (id) {
|
||||||
|
if (id.length !== 48 || /[^a-f0-9]/.test(id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
var createFileId = function () {
|
var createFileId = function () {
|
||||||
var id = uint8ArrayToHex(Nacl.randomBytes(24));
|
var id = uint8ArrayToHex(Nacl.randomBytes(24));
|
||||||
if (id.length !== 48 || /[^a-f0-9]/.test(id)) {
|
if (!testFileId(id)) {
|
||||||
throw new Error('file ids must consist of 48 hex characters');
|
throw new Error('file ids must consist of 48 hex characters');
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
@ -876,7 +882,7 @@ var upload = function (Env, publicKey, content, cb) {
|
|||||||
var session = getSession(Env.Sessions, publicKey);
|
var session = getSession(Env.Sessions, publicKey);
|
||||||
|
|
||||||
if (typeof(session.currentUploadSize) !== 'number' ||
|
if (typeof(session.currentUploadSize) !== 'number' ||
|
||||||
typeof(session.currentUploadSize) !== 'number') {
|
typeof(session.pendingUploadSize) !== 'number') {
|
||||||
// improperly initialized... maybe they didn't check before uploading?
|
// improperly initialized... maybe they didn't check before uploading?
|
||||||
// reject it, just in case
|
// reject it, just in case
|
||||||
return cb('NOT_READY');
|
return cb('NOT_READY');
|
||||||
@ -902,12 +908,12 @@ var upload = function (Env, publicKey, content, cb) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var upload_cancel = function (Env, publicKey, cb) {
|
var upload_cancel = function (Env, publicKey, fileSize, cb) {
|
||||||
var paths = Env.paths;
|
var paths = Env.paths;
|
||||||
|
|
||||||
var session = getSession(Env.Sessions, publicKey);
|
var session = getSession(Env.Sessions, publicKey);
|
||||||
delete session.currentUploadSize;
|
session.pendingUploadSize = fileSize;
|
||||||
delete session.pendingUploadSize;
|
session.currentUploadSize = 0;
|
||||||
if (session.blobstage) { session.blobstage.close(); }
|
if (session.blobstage) { session.blobstage.close(); }
|
||||||
|
|
||||||
var path = makeFilePath(paths.staging, publicKey);
|
var path = makeFilePath(paths.staging, publicKey);
|
||||||
@ -933,13 +939,14 @@ var isFile = function (filePath, cb) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var upload_complete = function (Env, publicKey, cb) {
|
var upload_complete = function (Env, publicKey, id, cb) {
|
||||||
var paths = Env.paths;
|
var paths = Env.paths;
|
||||||
var session = getSession(Env.Sessions, publicKey);
|
var session = getSession(Env.Sessions, publicKey);
|
||||||
|
|
||||||
if (session.blobstage && session.blobstage.close) {
|
if (!testFileId(id)) {
|
||||||
session.blobstage.close();
|
console.log(id);
|
||||||
delete session.blobstage;
|
WARN('uploadComplete', "id is invalid");
|
||||||
|
return void cb('RENAME_ERR');
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldPath = makeFilePath(paths.staging, publicKey);
|
var oldPath = makeFilePath(paths.staging, publicKey);
|
||||||
@ -948,8 +955,7 @@ var upload_complete = function (Env, publicKey, cb) {
|
|||||||
return void cb('RENAME_ERR');
|
return void cb('RENAME_ERR');
|
||||||
}
|
}
|
||||||
|
|
||||||
var tryRandomLocation = function (cb) {
|
var tryLocation = function (cb) {
|
||||||
var id = createFileId();
|
|
||||||
var prefix = id.slice(0, 2);
|
var prefix = id.slice(0, 2);
|
||||||
var newPath = makeFilePath(paths.blob, id);
|
var newPath = makeFilePath(paths.blob, id);
|
||||||
if (typeof(newPath) !== 'string') {
|
if (typeof(newPath) !== 'string') {
|
||||||
@ -968,7 +974,8 @@ var upload_complete = function (Env, publicKey, cb) {
|
|||||||
return void cb(e);
|
return void cb(e);
|
||||||
}
|
}
|
||||||
if (yes) {
|
if (yes) {
|
||||||
return void tryRandomLocation(cb);
|
WARN('isFile', 'FILE EXISTS!');
|
||||||
|
return void cb('RENAME_ERR');
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(void 0, newPath, id);
|
cb(void 0, newPath, id);
|
||||||
@ -976,38 +983,27 @@ var upload_complete = function (Env, publicKey, cb) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var retries = 3;
|
|
||||||
|
|
||||||
var handleMove = function (e, newPath, id) {
|
var handleMove = function (e, newPath, id) {
|
||||||
if (e || !oldPath || !newPath) {
|
if (e || !oldPath || !newPath) {
|
||||||
if (retries--) {
|
return void cb(e || 'PATH_ERR');
|
||||||
setTimeout(function () {
|
}
|
||||||
return tryRandomLocation(handleMove);
|
|
||||||
}, 750);
|
if (session.blobstage && session.blobstage.close) {
|
||||||
} else {
|
session.blobstage.close();
|
||||||
cb(e);
|
delete session.blobstage;
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// lol wut handle ur errors
|
// lol wut handle ur errors
|
||||||
Fs.rename(oldPath, newPath, function (e) {
|
Fs.rename(oldPath, newPath, function (e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
WARN('rename', e);
|
WARN('rename', e);
|
||||||
|
|
||||||
if (retries--) {
|
|
||||||
return void setTimeout(function () {
|
|
||||||
tryRandomLocation(handleMove);
|
|
||||||
}, 750);
|
|
||||||
}
|
|
||||||
|
|
||||||
return void cb('RENAME_ERR');
|
return void cb('RENAME_ERR');
|
||||||
}
|
}
|
||||||
cb(void 0, id);
|
cb(void 0, id);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
tryRandomLocation(handleMove);
|
tryLocation(handleMove);
|
||||||
};
|
};
|
||||||
|
|
||||||
var owned_upload_complete = function (Env, safeKey, cb) {
|
var owned_upload_complete = function (Env, safeKey, cb) {
|
||||||
@ -1504,7 +1500,7 @@ RPC.create = function (
|
|||||||
});
|
});
|
||||||
case 'UPLOAD_COMPLETE':
|
case 'UPLOAD_COMPLETE':
|
||||||
if (!privileged) { return deny(); }
|
if (!privileged) { return deny(); }
|
||||||
return void upload_complete(Env, safeKey, function (e, hash) {
|
return void upload_complete(Env, safeKey, msg[1], function (e, hash) {
|
||||||
WARN(e, hash);
|
WARN(e, hash);
|
||||||
Respond(e, hash);
|
Respond(e, hash);
|
||||||
});
|
});
|
||||||
@ -1516,8 +1512,11 @@ RPC.create = function (
|
|||||||
});
|
});
|
||||||
case 'UPLOAD_CANCEL':
|
case 'UPLOAD_CANCEL':
|
||||||
if (!privileged) { return deny(); }
|
if (!privileged) { return deny(); }
|
||||||
return void upload_cancel(Env, safeKey, function (e) {
|
// msg[1] is fileSize
|
||||||
WARN(e);
|
// if we pass it here, we can start an upload right away without calling
|
||||||
|
// UPLOAD_STATUS again
|
||||||
|
return void upload_cancel(Env, safeKey, msg[1], function (e) {
|
||||||
|
WARN(e, 'UPLOAD_CANCEL');
|
||||||
Respond(e);
|
Respond(e);
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -67,23 +67,6 @@ define([
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// V1
|
|
||||||
/*var getEditHashFromKeys = Hash.getEditHashFromKeys = function (chanKey, keys) {
|
|
||||||
if (typeof keys === 'string') {
|
|
||||||
return chanKey + keys;
|
|
||||||
}
|
|
||||||
if (!keys.editKeyStr) { return; }
|
|
||||||
return '/1/edit/' + hexToBase64(chanKey) + '/'+Crypto.b64RemoveSlashes(keys.editKeyStr)+'/';
|
|
||||||
};
|
|
||||||
var getViewHashFromKeys = Hash.getViewHashFromKeys = function (chanKey, keys) {
|
|
||||||
if (typeof keys === 'string') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return '/1/view/' + hexToBase64(chanKey) + '/'+Crypto.b64RemoveSlashes(keys.viewKeyStr)+'/';
|
|
||||||
};
|
|
||||||
var getFileHashFromKeys = Hash.getFileHashFromKeys = function (fileKey, cryptKey) {
|
|
||||||
return '/1/' + hexToBase64(fileKey) + '/' + Crypto.b64RemoveSlashes(cryptKey) + '/';
|
|
||||||
};*/
|
|
||||||
Hash.getUserHrefFromKeys = function (origin, username, pubkey) {
|
Hash.getUserHrefFromKeys = function (origin, username, pubkey) {
|
||||||
return origin + '/user/#/1/' + username + '/' + pubkey.replace(/\//g, '-');
|
return origin + '/user/#/1/' + username + '/' + pubkey.replace(/\//g, '-');
|
||||||
};
|
};
|
||||||
@ -108,7 +91,7 @@ define([
|
|||||||
password: Boolean(password),
|
password: Boolean(password),
|
||||||
version: 2,
|
version: 2,
|
||||||
type: type,
|
type: type,
|
||||||
keys: cryptor.fileKeyStr
|
keys: cryptor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cryptor = Crypto.createEditCryptor2(void 0, void 0, password);
|
cryptor = Crypto.createEditCryptor2(void 0, void 0, password);
|
||||||
@ -116,7 +99,7 @@ define([
|
|||||||
password: Boolean(password),
|
password: Boolean(password),
|
||||||
version: 2,
|
version: 2,
|
||||||
type: type,
|
type: type,
|
||||||
keys: cryptor.editKeyStr
|
keys: cryptor
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -374,8 +357,8 @@ Version 1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (parsed.type === "file") {
|
} else if (parsed.type === "file") {
|
||||||
secret.channel = base64ToHex(secret.keys.chanId);
|
|
||||||
secret.keys = Crypto.createFileCryptor2(parsed.key, password);
|
secret.keys = Crypto.createFileCryptor2(parsed.key, password);
|
||||||
|
secret.channel = base64ToHex(secret.keys.chanId);
|
||||||
secret.key = secret.keys.fileKeyStr;
|
secret.key = secret.keys.fileKeyStr;
|
||||||
if (secret.channel.length !== 48 || secret.key.length !== 24) {
|
if (secret.channel.length !== 48 || secret.key.length !== 24) {
|
||||||
throw new Error("The channel key and/or the encryption key is invalid");
|
throw new Error("The channel key and/or the encryption key is invalid");
|
||||||
|
|||||||
@ -204,8 +204,8 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
common.uploadComplete = function (cb) {
|
common.uploadComplete = function (id, cb) {
|
||||||
postMessage("UPLOAD_COMPLETE", null, function (obj) {
|
postMessage("UPLOAD_COMPLETE", id, function (obj) {
|
||||||
if (obj && obj.error) { return void cb(obj.error); }
|
if (obj && obj.error) { return void cb(obj.error); }
|
||||||
cb(null, obj);
|
cb(null, obj);
|
||||||
});
|
});
|
||||||
@ -218,8 +218,8 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
common.uploadCancel = function (cb) {
|
common.uploadCancel = function (size, cb) {
|
||||||
postMessage("UPLOAD_CANCEL", null, function (obj) {
|
postMessage("UPLOAD_CANCEL", {size: size}, function (obj) {
|
||||||
if (obj && obj.error) { return void cb(obj.error); }
|
if (obj && obj.error) { return void cb(obj.error); }
|
||||||
cb(null, obj);
|
cb(null, obj);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -230,9 +230,9 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Store.uploadComplete = function (data, cb) {
|
Store.uploadComplete = function (id, cb) {
|
||||||
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
||||||
store.rpc.uploadComplete(function (err, res) {
|
store.rpc.uploadComplete(id, function (err, res) {
|
||||||
if (err) { return void cb({error:err}); }
|
if (err) { return void cb({error:err}); }
|
||||||
cb(res);
|
cb(res);
|
||||||
});
|
});
|
||||||
@ -248,7 +248,7 @@ define([
|
|||||||
|
|
||||||
Store.uploadCancel = function (data, cb) {
|
Store.uploadCancel = function (data, cb) {
|
||||||
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
||||||
store.rpc.uploadCancel(function (err, res) {
|
store.rpc.uploadCancel(data.size, function (err, res) {
|
||||||
if (err) { return void cb({error:err}); }
|
if (err) { return void cb({error:err}); }
|
||||||
cb(res);
|
cb(res);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -13,16 +13,14 @@ define([
|
|||||||
// if it exists, path contains the new pad location in the drive
|
// if it exists, path contains the new pad location in the drive
|
||||||
var path = file.path;
|
var path = file.path;
|
||||||
|
|
||||||
// XXX
|
var password = file.password;
|
||||||
// PASSWORD_FILES
|
|
||||||
var password;
|
|
||||||
var hash = Hash.createRandomHash('file', password);
|
var hash = Hash.createRandomHash('file', password);
|
||||||
var secret = Hash.getSecrets('file', hash, password);
|
var secret = Hash.getSecrets('file', hash, password);
|
||||||
var key = secret.keys.cryptKey;
|
var key = secret.keys.cryptKey;
|
||||||
var id = secret.channel;
|
var id = secret.channel;
|
||||||
//var key = Nacl.randomBytes(32);
|
|
||||||
|
|
||||||
// XXX provide channel id to "next"
|
// XXX check id here (getFileSize)
|
||||||
|
|
||||||
var next = FileCrypto.encrypt(u8, metadata, key);
|
var next = FileCrypto.encrypt(u8, metadata, key);
|
||||||
|
|
||||||
var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata);
|
var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata);
|
||||||
@ -53,7 +51,7 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if not box then done
|
// if not box then done
|
||||||
common.uploadComplete(function (e/*, id*/) { // XXX id is given, not asked
|
common.uploadComplete(id, function (e) {
|
||||||
if (e) { return void console.error(e); }
|
if (e) { return void console.error(e); }
|
||||||
var uri = ['', 'blob', id.slice(0,2), id].join('/');
|
var uri = ['', 'blob', id.slice(0,2), id].join('/');
|
||||||
console.log("encrypted blob is now available as %s", uri);
|
console.log("encrypted blob is now available as %s", uri);
|
||||||
@ -64,11 +62,11 @@ define([
|
|||||||
|
|
||||||
if (noStore) { return void onComplete(href); }
|
if (noStore) { return void onComplete(href); }
|
||||||
|
|
||||||
// PASSWORD_FILES
|
|
||||||
var data = {
|
var data = {
|
||||||
title: title || "",
|
title: title || "",
|
||||||
href: href,
|
href: href,
|
||||||
path: path,
|
path: path,
|
||||||
|
password: password,
|
||||||
channel: id
|
channel: id
|
||||||
};
|
};
|
||||||
common.setPadTitle(data, function (err) {
|
common.setPadTitle(data, function (err) {
|
||||||
@ -89,11 +87,10 @@ define([
|
|||||||
if (pending) {
|
if (pending) {
|
||||||
return void onPending(function () {
|
return void onPending(function () {
|
||||||
// if the user wants to cancel the pending upload to execute that one
|
// if the user wants to cancel the pending upload to execute that one
|
||||||
common.uploadCancel(function (e, res) {
|
common.uploadCancel(estimate, function (e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
return void console.error(e);
|
return void console.error(e);
|
||||||
}
|
}
|
||||||
console.log(res);
|
|
||||||
next(again);
|
next(again);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -176,8 +176,8 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exp.uploadComplete = function (cb) {
|
exp.uploadComplete = function (id, cb) {
|
||||||
rpc.send('UPLOAD_COMPLETE', null, function (e, res) {
|
rpc.send('UPLOAD_COMPLETE', id, function (e, res) {
|
||||||
if (e) { return void cb(e); }
|
if (e) { return void cb(e); }
|
||||||
var id = res[0];
|
var id = res[0];
|
||||||
if (typeof(id) !== 'string') {
|
if (typeof(id) !== 'string') {
|
||||||
@ -203,8 +203,8 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exp.uploadCancel = function (cb) {
|
exp.uploadCancel = function (size, cb) {
|
||||||
rpc.send('UPLOAD_CANCEL', void 0, function (e) {
|
rpc.send('UPLOAD_CANCEL', size, function (e) {
|
||||||
if (e) { return void cb(e); }
|
if (e) { return void cb(e); }
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user