Put a signature on sent group messages
It's important that group messages be signed by the sender, rather than by a secret derived from the shared secret.
This commit is contained in:
parent
7c5ab63fd8
commit
803672931a
1 changed files with 69 additions and 20 deletions
|
@ -2,12 +2,23 @@
|
||||||
* browser.
|
* browser.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function buttonAndTextElement(buttonLabel, textContent, clickHandler) {
|
function buttonElement(buttonLabel, clickHandler) {
|
||||||
var el = document.createElement("div");
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
el.appendChild(button);
|
|
||||||
button.appendChild(document.createTextNode(buttonLabel));
|
button.appendChild(document.createTextNode(buttonLabel));
|
||||||
|
button.addEventListener("click", clickHandler, false);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buttonsAndText(textContent, buttonLabelToHandlerMap) {
|
||||||
|
var el = document.createElement("div");
|
||||||
|
for (var label in buttonLabelToHandlerMap) {
|
||||||
|
if (!buttonLabelToHandlerMap.hasOwnProperty(label)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var handler = buttonLabelToHandlerMap[label];
|
||||||
|
var button = buttonElement(label, handler);
|
||||||
|
el.appendChild(button);
|
||||||
|
}
|
||||||
|
|
||||||
var message_element = document.createElement("tt");
|
var message_element = document.createElement("tt");
|
||||||
el.appendChild(message_element);
|
el.appendChild(message_element);
|
||||||
|
@ -15,22 +26,33 @@ function buttonAndTextElement(buttonLabel, textContent, clickHandler) {
|
||||||
var content = document.createTextNode(textContent);
|
var content = document.createTextNode(textContent);
|
||||||
message_element.appendChild(content);
|
message_element.appendChild(content);
|
||||||
|
|
||||||
el.addEventListener("click", clickHandler, false);
|
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buttonAndTextElement(buttonLabel, textContent, clickHandler) {
|
||||||
|
var buttonMap = {};
|
||||||
|
buttonMap[buttonLabel] = clickHandler;
|
||||||
|
return buttonsAndText(textContent, buttonMap);
|
||||||
|
}
|
||||||
|
|
||||||
function DemoUser(name) {
|
function DemoUser(name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.olmAccount = new Olm.Account();
|
this.olmAccount = new Olm.Account();
|
||||||
this.olmAccount.create();
|
this.olmAccount.create();
|
||||||
|
|
||||||
|
this.idKey = this.getIdKeys()["curve25519"];
|
||||||
|
|
||||||
/* the people in our chat, indexed by their Curve25519 identity key.
|
/* the people in our chat, indexed by their Curve25519 identity key.
|
||||||
*/
|
*/
|
||||||
this.peers = {};
|
this.peers = {};
|
||||||
|
|
||||||
|
/* the Ed25519 signing key for each peer, indexed by their Curve25519 id key
|
||||||
|
*/
|
||||||
|
this.peerSigningKeys = {};
|
||||||
|
|
||||||
/* for each peer, a one-to-one session - indexed by id key and created on
|
/* for each peer, a one-to-one session - indexed by id key and created on
|
||||||
* demand */
|
* demand */
|
||||||
this.peerSessions = {}
|
this.peerSessions = {};
|
||||||
|
|
||||||
/* for each peer, info on their sender session - indexed by id key and
|
/* for each peer, info on their sender session - indexed by id key and
|
||||||
* session id */
|
* session id */
|
||||||
|
@ -45,7 +67,7 @@ function DemoUser(name) {
|
||||||
|
|
||||||
/* the operations our peers are allowed to do on us */
|
/* the operations our peers are allowed to do on us */
|
||||||
var publicOps = [
|
var publicOps = [
|
||||||
"getIdKey", "getOneTimeKey",
|
"getIdKeys", "getOneTimeKey",
|
||||||
"receiveOneToOne", "receiveGroup",
|
"receiveOneToOne", "receiveGroup",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -135,13 +157,14 @@ DemoUser.prototype.addTask = function(description, task, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
DemoUser.prototype.addPeer = function(peerOps) {
|
DemoUser.prototype.addPeer = function(peerOps) {
|
||||||
var id = peerOps.getIdKey();
|
var keys = peerOps.getIdKeys();
|
||||||
|
var id = keys["curve25519"];
|
||||||
this.peers[id] = peerOps;
|
this.peers[id] = peerOps;
|
||||||
|
this.peerSigningKeys[id] = keys["ed25519"];
|
||||||
};
|
};
|
||||||
|
|
||||||
DemoUser.prototype.getIdKey = function() {
|
DemoUser.prototype.getIdKeys = function() {
|
||||||
var keys = JSON.parse(this.olmAccount.identity_keys());
|
return JSON.parse(this.olmAccount.identity_keys());
|
||||||
return keys.curve25519;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DemoUser.prototype.generateKeys = function(callback) {
|
DemoUser.prototype.generateKeys = function(callback) {
|
||||||
|
@ -203,7 +226,7 @@ DemoUser.prototype.sendToPeer = function(peerId, message, callback) {
|
||||||
self.addTask("encrypt one-to-one message", function(done) {
|
self.addTask("encrypt one-to-one message", function(done) {
|
||||||
var encrypted = session.encrypt(message);
|
var encrypted = session.encrypt(message);
|
||||||
var packet = {
|
var packet = {
|
||||||
sender_key: self.getIdKey(),
|
sender_key: self.idKey,
|
||||||
ciphertext: encrypted,
|
ciphertext: encrypted,
|
||||||
};
|
};
|
||||||
var json = JSON.stringify(packet);
|
var json = JSON.stringify(packet);
|
||||||
|
@ -357,6 +380,16 @@ DemoUser.prototype.decryptGroup = function(jsonpacket, callback) {
|
||||||
var sender = packet.sender_key;
|
var sender = packet.sender_key;
|
||||||
var session_id = packet.session_id;
|
var session_id = packet.session_id;
|
||||||
|
|
||||||
|
var sender_signing_key = self.peerSigningKeys[sender];
|
||||||
|
if (!sender_signing_key) {
|
||||||
|
throw new Error("No known signing key for sender "+sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
var olmUtility = new Olm.Utility();
|
||||||
|
olmUtility.ed25519_verify(
|
||||||
|
sender_signing_key, packet.body, packet.signature
|
||||||
|
);
|
||||||
|
|
||||||
var peer_sessions = self.peerGroupSessions[sender];
|
var peer_sessions = self.peerGroupSessions[sender];
|
||||||
if (!peer_sessions) {
|
if (!peer_sessions) {
|
||||||
throw new Error("No sessions for sender "+sender);
|
throw new Error("No sessions for sender "+sender);
|
||||||
|
@ -383,22 +416,37 @@ DemoUser.prototype.encrypt = function(message) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var session = this.getGroupSession();
|
var session = this.getGroupSession();
|
||||||
|
|
||||||
|
function sendJsonToPeers(json) {
|
||||||
|
for (var peer in self.peers) {
|
||||||
|
if (!self.peers.hasOwnProperty(peer)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.peers[peer].receiveGroup(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
self.addTask("encrypt group message", function(done) {
|
self.addTask("encrypt group message", function(done) {
|
||||||
var encrypted = session.encrypt(message);
|
var encrypted = session.encrypt(message);
|
||||||
|
var signature = self.olmAccount.sign(encrypted);
|
||||||
|
|
||||||
var packet = {
|
var packet = {
|
||||||
sender_key: self.getIdKey(),
|
sender_key: self.idKey,
|
||||||
session_id: session.session_id(),
|
session_id: session.session_id(),
|
||||||
body: encrypted,
|
body: encrypted,
|
||||||
|
signature: signature,
|
||||||
};
|
};
|
||||||
var json = JSON.stringify(packet);
|
var json = JSON.stringify(packet);
|
||||||
|
|
||||||
var el = buttonAndTextElement("send", json, function(ev) {
|
var el = buttonsAndText(json, {
|
||||||
for (var peer in self.peers) {
|
send: function(ev) {
|
||||||
if (!self.peers.hasOwnProperty(peer)) {
|
sendJsonToPeers(json);
|
||||||
continue;
|
},
|
||||||
}
|
"send corrupted": function(ev) {
|
||||||
self.peers[peer].receiveGroup(json);
|
var p = JSON.parse(json);
|
||||||
}
|
p.body += " ";
|
||||||
|
sendJsonToPeers(JSON.stringify(p));
|
||||||
|
},
|
||||||
});
|
});
|
||||||
self.groupOutputDiv.appendChild(el);
|
self.groupOutputDiv.appendChild(el);
|
||||||
done();
|
done();
|
||||||
|
@ -406,6 +454,7 @@ DemoUser.prototype.encrypt = function(message) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
function initUserDiv(demoUser, div) {
|
function initUserDiv(demoUser, div) {
|
||||||
demoUser.progressElement = div.getElementsByClassName("user_progress")[0];
|
demoUser.progressElement = div.getElementsByClassName("user_progress")[0];
|
||||||
|
|
Loading…
Reference in a new issue