mirror of https://github.com/xwiki-labs/cryptpad
Ability to send a read-only URL
This commit is contained in:
parent
721cb8fed1
commit
368e253c9f
|
@ -1,5 +1,6 @@
|
|||
;(function () { 'use strict';
|
||||
const Crypto = require('crypto');
|
||||
const Nacl = require('tweetnacl');
|
||||
const LogStore = require('./storage/LogStore');
|
||||
|
||||
|
||||
|
@ -27,6 +28,15 @@ const sendMsg = function (ctx, user, msg) {
|
|||
|
||||
const sendChannelMessage = function (ctx, channel, msgStruct) {
|
||||
msgStruct.unshift(0);
|
||||
if (msgStruct[2] === 'MSG' && channel.validateKey) {
|
||||
let msg = Nacl.util.decodeBase64(msgStruct[4]);
|
||||
let validated = Nacl.sign.open(msg, channel.validateKey);
|
||||
if (!validated) {
|
||||
console.log("Unsigned message rejected");
|
||||
return;
|
||||
}
|
||||
msgStruct[4] = Nacl.util.encodeUTF8(validated);
|
||||
}
|
||||
channel.forEach(function (user) {
|
||||
if(msgStruct[2] !== 'MSG' || user.id !== msgStruct[1]) { // We don't want to send back a message to its sender, in order to save bandwidth
|
||||
sendMsg(ctx, user, msgStruct);
|
||||
|
@ -149,6 +159,17 @@ const handleMessage = function (ctx, user, msg) {
|
|||
clearTimeout(ctx.timeouts[chanName]);
|
||||
}
|
||||
|
||||
// validation key?
|
||||
if (json[2]) {
|
||||
if (chan.validateKey && Nacl.util.encodeBase64(chan.validateKey) !== json[2]) {
|
||||
sendMsg(ctx, user, [seq, 'ERROR', 'INVALID_KEY', obj]);
|
||||
return;
|
||||
}
|
||||
if (!chan.validateKey) {
|
||||
chan.validateKey = Nacl.util.decodeBase64(json[2]);
|
||||
}
|
||||
}
|
||||
|
||||
chan.id = chanName;
|
||||
if (USE_HISTORY_KEEPER) {
|
||||
sendMsg(ctx, user, [0, HISTORY_KEEPER_ID, 'JOIN', chanName]);
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
"dependencies": {
|
||||
"express": "~4.10.1",
|
||||
"ws": "^1.0.1",
|
||||
"nthen": "~0.1.0"
|
||||
"nthen": "~0.1.0",
|
||||
"tweetnacl": "~0.12.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jshint": "~2.9.1",
|
||||
|
|
|
@ -128,7 +128,7 @@ define([
|
|||
|
||||
var base64ToHex = common.base64ToHex = function (b64String) {
|
||||
var hexArray = [];
|
||||
atob(b64String.replace(/-/g, '/') + "==").split("").forEach(function(e){
|
||||
atob(b64String.replace(/-/g, '/')).split("").forEach(function(e){
|
||||
var h = e.charCodeAt(0).toString(16);
|
||||
if (h.length === 1) { h = "0"+h; }
|
||||
hexArray.push(h);
|
||||
|
@ -136,18 +136,28 @@ define([
|
|||
return hexArray.join("");
|
||||
};
|
||||
|
||||
var getHashFromKeys = common.getHashFromKeys = function (chanKey, cryptKey) {
|
||||
return '/1/' + hexToBase64(chanKey) + '/' + cryptKey.replace(/\//g, '-');
|
||||
|
||||
var getEditHashFromKeys = common.getEditHashFromKeys = function (chanKey, keys) {
|
||||
if (typeof keys === 'string') {
|
||||
return chanKey + Crypto.b64RemoveSlashes(keys);
|
||||
}
|
||||
return '/1/edit/' + hexToBase64(chanKey) + '/' + Crypto.b64RemoveSlashes(keys.editKeyStr);
|
||||
};
|
||||
var getViewHashFromKeys = common.getViewHashFromKeys = function (chanKey, keys) {
|
||||
return '/1/view/' + hexToBase64(chanKey) + '/' + Crypto.b64RemoveSlashes(keys.viewKeyStr);
|
||||
};
|
||||
var getHashFromKeys = common.getHashFromKeys = getEditHashFromKeys;
|
||||
|
||||
var getSecrets = common.getSecrets = function () {
|
||||
var secret = {};
|
||||
if (!/#/.test(window.location.href)) {
|
||||
secret.key = Crypto.genKey();
|
||||
secret.keys = Crypto.createEditCryptor();
|
||||
secret.key = Crypto.createEditCryptor().editKeyStr;
|
||||
} else {
|
||||
var hash = window.location.hash.slice(1);
|
||||
if (hash.length === 0) {
|
||||
secret.key = Crypto.genKey();
|
||||
secret.keys = Crypto.createEditCryptor();
|
||||
secret.key = Crypto.createEditCryptor().editKeyStr;
|
||||
return secret;
|
||||
}
|
||||
common.redirect(hash);
|
||||
|
@ -166,15 +176,35 @@ define([
|
|||
throw new Error("Unable to parse the key");
|
||||
}
|
||||
var version = hashArray[1];
|
||||
if (version === "1") {
|
||||
/*if (version === "1") {
|
||||
secret.channel = base64ToHex(hashArray[2]);
|
||||
secret.key = hashArray[3].replace(/-/g, '/'); //TODO replace / by -
|
||||
if (secret.channel.length !== 32 || secret.key.length !== 24) {
|
||||
common.alert("The channel key and/or the encryption key is invalid");
|
||||
console.log("Channel key length : " + secret.channel.length + " != 32");
|
||||
console.log("Encryption key length : " + secret.key.length + " != 24");
|
||||
throw new Error("The channel key and/or the encryption key is invalid");
|
||||
}
|
||||
}*/
|
||||
if (version === "1") {
|
||||
var mode = hashArray[2];
|
||||
if (mode === 'edit') {
|
||||
secret.channel = base64ToHex(hashArray[3]);
|
||||
var keys = Crypto.createEditCryptor(hashArray[4].replace(/-/g, '/'));
|
||||
secret.keys = keys;
|
||||
secret.key = keys.editKeyStr;
|
||||
if (secret.channel.length !== 32 || secret.key.length !== 24) {
|
||||
common.alert("The channel key and/or the encryption key is invalid");
|
||||
throw new Error("The channel key and/or the encryption key is invalid");
|
||||
}
|
||||
}
|
||||
else if (mode === 'view') {
|
||||
secret.channel = base64ToHex(hashArray[3]);
|
||||
var keys = Crypto.createViewCryptor(hashArray[4].replace(/-/g, '/'));
|
||||
secret.keys = keys;
|
||||
if (secret.channel.length !== 32) {
|
||||
common.alert("The channel key is invalid");
|
||||
throw new Error("The channel key is invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,6 @@ define([
|
|||
} else {
|
||||
module.spinner.show();
|
||||
}
|
||||
|
||||
inner.setAttribute('contenteditable', bool);
|
||||
};
|
||||
|
||||
|
@ -317,14 +316,15 @@ define([
|
|||
// the channel we will communicate over
|
||||
channel: secret.channel,
|
||||
|
||||
// our encryption key
|
||||
cryptKey: secret.key,
|
||||
// our public key. send -1 if view mode
|
||||
validateKey: secret.keys.validateKey || undefined,
|
||||
readOnly: secret.keys.editKeyStr ? undefined : 1,
|
||||
|
||||
// method which allows us to get the id of the user
|
||||
setMyID: setMyID,
|
||||
|
||||
// Pass in encrypt and decrypt methods
|
||||
crypto: Crypto.createEncryptor(secret.key),
|
||||
crypto: Crypto.createEncryptor(secret.keys),
|
||||
|
||||
// really basic operational transform
|
||||
transformFunction : JsonOT.validate,
|
||||
|
@ -545,7 +545,10 @@ define([
|
|||
$rightside.append($forgetPad);
|
||||
|
||||
// set the hash
|
||||
window.location.hash = Cryptpad.getHashFromKeys(info.channel, secret.key);
|
||||
if (secret.keys.editKeyStr) {
|
||||
window.location.hash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys);
|
||||
}
|
||||
console.log("View Hash : " + Cryptpad.getViewHashFromKeys(info.channel, secret.keys));
|
||||
|
||||
Cryptpad.getPadTitle(function (err, title) {
|
||||
if (err) {
|
||||
|
|
Loading…
Reference in New Issue