[security] Add security number to PeerUI to make verification of peer-to-peer encryption possible.

This commit is contained in:
schlagmichdoch 2023-02-16 02:19:14 +01:00
parent e9b23bfdb0
commit c5d0eaa034
9 changed files with 131 additions and 23 deletions

View file

@ -568,7 +568,7 @@ class RTCPeer extends Peer {
_onChannelOpened(event) {
console.log('RTC: channel opened with', this._peerId);
Events.fire('peer-connected', this._peerId);
Events.fire('peer-connected', {peerId: this._peerId, connectionHash: this.getConnectionHash()});
const channel = event.channel || event.target;
channel.binaryType = 'arraybuffer';
channel.onmessage = e => this._onMessage(e.data);
@ -578,6 +578,32 @@ class RTCPeer extends Peer {
this._channel = channel;
}
getConnectionHash() {
const localDescriptionLines = this._conn.localDescription.sdp.split("\r\n");
const remoteDescriptionLines = this._conn.remoteDescription.sdp.split("\r\n");
let localConnectionFingerprint, remoteConnectionFingerprint;
for (let i=0; i<localDescriptionLines.length; i++) {
if (localDescriptionLines[i].startsWith("a=fingerprint:")) {
localConnectionFingerprint = localDescriptionLines[i].substring(14);
break;
}
}
for (let i=0; i<remoteDescriptionLines.length; i++) {
if (remoteDescriptionLines[i].startsWith("a=fingerprint:")) {
remoteConnectionFingerprint = remoteDescriptionLines[i].substring(14);
break;
}
}
const combinedFingerprints = this._isCaller
? localConnectionFingerprint + remoteConnectionFingerprint
: remoteConnectionFingerprint + localConnectionFingerprint;
let hash = cyrb53(combinedFingerprints).toString();
while (hash.length < 16) {
hash = "0" + hash;
}
return hash;
}
_onBeforeUnload(e) {
if (this._busy) {
e.preventDefault();
@ -679,11 +705,16 @@ class WSPeer extends Peer {
}
onServerMessage(message) {
Events.fire('peer-connected', message.sender.id)
Events.fire('peer-connected', {peerId: message.sender.id, connectionHash: this.getConnectionHash()})
if (this._peerId) return;
this._peerId = message.sender.id;
this._sendSignal();
}
getConnectionHash() {
// Todo: implement SubtleCrypto asymmetric encryption and create connectionHash from public keys
return "";
}
}
class PeersManager {

View file

@ -19,7 +19,7 @@ class PeersUI {
constructor() {
Events.on('peer-joined', e => this._onPeerJoined(e.detail));
Events.on('peer-connected', e => this._onPeerConnected(e.detail));
Events.on('peer-connected', e => this._onPeerConnected(e.detail.peerId, e.detail.connectionHash));
Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
Events.on('peers', e => this._onPeers(e.detail));
Events.on('set-progress', e => this._onSetProgress(e.detail));
@ -63,9 +63,9 @@ class PeersUI {
this.peers[peer.id] = peer;
}
_onPeerConnected(peerId) {
_onPeerConnected(peerId, connectionHash) {
if(this.peers[peerId] && !$(peerId))
new PeerUI(this.peers[peerId]);
new PeerUI(this.peers[peerId], connectionHash);
}
_redrawPeer(peer) {
@ -235,17 +235,21 @@ class PeerUI {
<div class="name font-subheading"></div>
<div class="device-name font-body2"></div>
<div class="status font-body2"></div>
<span class="connection-hash font-body2" title="To verify the security of the end-to-end encryption, compare this security number on both devices"></span>
</label>`;
this.$el.querySelector('svg use').setAttribute('xlink:href', this._icon());
this.$el.querySelector('.name').textContent = this._displayName();
this.$el.querySelector('.device-name').textContent = this._deviceName();
this.$el.querySelector('.connection-hash').textContent =
this._connectionHash.substring(0, 4) + " " + this._connectionHash.substring(4, 8) + " " + this._connectionHash.substring(8, 12) + " " + this._connectionHash.substring(12, 16);
}
constructor(peer) {
constructor(peer, connectionHash) {
this._peer = peer;
this._roomType = peer.roomType;
this._roomSecret = peer.roomSecret;
this._connectionHash = connectionHash;
this._initDom();
this._bindListeners();
$$('x-peers').appendChild(this.$el);

View file

@ -381,6 +381,24 @@ const mime = (() => {
})();
/*
cyrb53 (c) 2018 bryc (github.com/bryc)
A fast and simple hash function with decent collision resistance.
Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity.
Public domain. Attribution appreciated.
*/
const cyrb53 = function(str, seed = 0) {
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
for (let i = 0, ch; i < str.length; i++) {
ch = str.charCodeAt(i);
h1 = Math.imul(h1 ^ ch, 2654435761);
h2 = Math.imul(h2 ^ ch, 1597334677);
}
h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909);
h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909);
return 4294967296 * (2097151 & h2) + (h1>>>0);
};
function arrayBufferToBase64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);