feat(login): add modal to ask for privkey

master
Romain J 10 months ago
parent 69426f220b
commit 0ab6dd705c
No known key found for this signature in database
GPG Key ID: 3227578329C2A3A7

@ -2,11 +2,13 @@ module.exports = {
root: true,
env: {
node: true,
"django/i18n": true
"django/i18n": true,
"es6": true
},
plugins: ["django"],
parserOptions: {
parser: 'babel-eslint',
"ecmaVersion": 2017
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',

@ -32,18 +32,6 @@ function createAttachments(attachments) {
}
function createMessage(data) {
const sharedKey = nacl.box.before(
nacl.util.decodeBase64(recipients[data.author.id]), usableKeyPair.secretKey
);
const message = {
box: nacl.util.decodeBase64(data.content),
nonce: nacl.util.decodeBase64(data.nonce)
}
const payload = nacl.box.open.after(message.box, message.nonce, sharedKey);
return `
<article class="uk-alert uk-comment uk-position-relative uk-padding-small uk-margin-small uk-border-rounded
message ${data.author.id === me ? 'message-me uk-alert-success' : 'uk-alert-primary'}

@ -129,5 +129,4 @@
});
</script>
{% include "layouts/components/message/decryptor.html" %}
{% endblock %}

@ -33,6 +33,3 @@
</div>
{% endblock %}
{% block inline_javascript %}
{% include "layouts/components/message/decryptor.html" %}
{% endblock %}

@ -80,42 +80,98 @@
</script>
{% endif %}
{% if user.is_authenticated and room_name %}
<div id="ws_error_modal" uk-modal>
{% if user.is_authenticated %}
{% if room_name %}
<div id="ws_error_modal" uk-modal>
<div class="uk-modal-dialog uk-modal-body">
<h2 class="uk-modal-title uk-text-danger">WebSocket Error</h2>
<p>
{% blocktrans %}
The connection with the websocket could not be established,
this problem can either come from your connection rules on the network,
or from a problem on the server.<br>
You can ignore this error and view your messages without the automatic refresh,
or try reloading the page.
{% endblocktrans %}
</p>
<p class="uk-text-right">
<button class="uk-button uk-button-default uk-modal-close"
type="button">{% trans "Dismiss" %}</button>
<a href="{{ request.get_full_path }}" class="uk-button uk-button-primary"
type="button">{% trans "Reload" %}</a>
</p>
</div>
</div>
<script>
window.room_name = {
id: '{{ room_name.id }}',
guild: {
name: '{{ room_name.guild.name }}',
id: '{{ room_name.guild.id }}',
},
}
</script>
{% compress js %}
<script src="{% static 'js/ws.js' %}"></script>
{% endcompress %}
{% endif %}
<div id="private_key_modal" uk-modal>
<div class="uk-modal-dialog uk-modal-body">
<h2 class="uk-modal-title uk-text-danger">WebSocket Error</h2>
<h2 class="uk-modal-title uk-text-info">Enter your private key</h2>
<div id="invalid_private_key" class="uk-hidden uk-alert uk-alert-danger">
<p>{% trans "Invalid private key passed" %}</p>
</div>
<p>
{% blocktrans %}
The connection with the websocket could not be established,
this problem can either come from your connection rules on the network,
or from a problem on the server.<br>
You can ignore this error and view your messages without the automatic refresh,
or try reloading the page.
thank you to inform your private key in order to be able to read and send messages. <br>
We remind you that this last one remains only on your navigator and is not in no case
communicated to the server
{% endblocktrans %}
</p>
<label>
<input id="private_key" type="text" class="uk-input" placeholder="Private key">
</label>
<p class="uk-text-right">
<button class="uk-button uk-button-default uk-modal-close"
type="button">{% trans "Dismiss" %}</button>
<a href="{{ request.get_full_path }}" class="uk-button uk-button-primary"
type="button">{% trans "Reload" %}</a>
type="button">{% trans "Enter" %}</button>
</p>
</div>
</div>
<script>
window.room_name = {
id: '{{ room_name.id }}',
guild: {
name: '{{ room_name.guild.name }}',
id: '{{ room_name.guild.id }}',
},
}
</script>
{% compress js %}
<script src="{% static 'js/ws.js' %}"></script>
{% endcompress %}
<script>
window.me = '{{ user.id }}'
window.me = '{{ user.id }}';
document.addEventListener("DOMContentLoaded", () => {
let private_key = document.getElementById("private_key");
let invalid_private_key = document.getElementById("invalid_private_key");
invalid_private_key.classList.add("uk-hidden");
if (window.sessionStorage.getItem("keySet") === null) {
let keySet_modal = UIkit.modal(document.getElementById("private_key_modal"));
keySet_modal.show();
UIkit.util.on(keySet_modal.$el, "hidden", () => {
try {
window.keyPair = nacl.box.keyPair.fromSecretKey(nacl.util.decodeBase64(private_key.value));
window.sessionStorage.setItem(
"keySet",
`${nacl.util.encodeBase64(keyPair.publicKey)}|${nacl.util.encodeBase64(keyPair.secretKey)}`
);
location.reload();
} catch (e) {
invalid_private_key.classList.remove("uk-hidden");
keySet_modal.show();
}
})
}
});
</script>
{% endif %}

@ -1,166 +0,0 @@
{% load static %}
<!-- BASE -->
<script src="{% static 'js/libs/kbpgp/kbpgp-2.1.0.js' %}"></script>
<script>
class ChatApi {
listenToMessages(room, onMessageReceived, onConnected) {
let source = new EventSource(`api/rooms/${room}`);
source.addEventListener("connected", () => onConnected());
source.addEventListener("message", evt => {
let message = JSON.parse(evt.data);
console.log("Message received", message);
onMessageReceived(message);
});
}
sendMessage(room, message) {
let req = new XMLHttpRequest();
req.open("POST", `api/rooms/${room}/messages/`);
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.send(JSON.stringify(JSON.stringify(message)));
console.log("Message sent", message);
}
}
</script>
<script>
class PgpKey {
constructor(key) {
this._key = key;
if (this.canDecrypt()) {
this._ring = new kbpgp.keyring.KeyRing();
this._ring.add_key_manager(key);
}
}
public() {
return this._key.armored_pgp_public;
}
id() {
return this._key.get_pgp_short_key_id();
}
nickname() {
return this._key.userids[0].get_username();
}
encrypt(text, onDone) {
kbpgp.box({msg: text, encrypt_for: this._key}, (_, cipher) =>
onDone(cipher));
}
canDecrypt() {
return this._key.can_decrypt();
}
decrypt(cipher, onDone) {
kbpgp.unbox({keyfetch: this._ring, armored: cipher, progress_hook: null}, (_, literals) =>
onDone(literals[0].toString()));
}
static generate(nickname, onDone) {
let opt = {userid: nickname, primary: {nbits: 1024}, subkeys: []};
kbpgp.KeyManager.generate(opt, (_, key) =>
key.sign(
{},
() =>
key.export_pgp_public(
{},
() => onDone(new PgpKey(key))
)
)
);
}
static load(publicKey, onDone) {
kbpgp.KeyManager.import_from_armored_pgp({armored: publicKey}, (_, key) =>
onDone(new PgpKey(key)));
}
}
</script>
<script>
function enterChat(onDone) {
let room = '{{ room_name.id }}';
let nickname = 'Anonymous' + (Math.random() * 100).toFixed(0);
let roomInput = document.querySelector('.lobby .room');
let nicknameInput = document.querySelector('.lobby .nickname');
roomInput.value = room;
nicknameInput.value = nickname;
roomInput.select();
document.querySelector('.lobby .join-form').addEventListener('submit', evt => {
evt.preventDefault();
room = roomInput.value;
nickname = nicknameInput.value;
if (room.length && nickname.length) {
document.querySelector('.lobby .join-form').innerText = 'Generating cryptographic key...';
PgpKey.generate(nickname, myKey => {
document.querySelector('.lobby').classList.add('hidden');
window.history.pushState(null, null, '#room/' + window.encodeURI(room));
onDone(room, nickname, myKey);
});
}
});
}
function joinChat(room, nickname, myKey) {
let logs = document.querySelector(".chat .logs");
let newMessage = document.querySelector('.chat .new-message');
let chatApi = new ChatApi();
let keys = {};
document.querySelector('.chat .new-message-form').addEventListener('submit', evt => {
evt.preventDefault();
Object.keys(keys).forEach(keyId =>
keys[keyId].encrypt(newMessage.value, cipher =>
chatApi.sendMessage(room, {sender: myKey.id(), recipient: keyId, text: cipher})));
newMessage.value = '';
});
chatApi.listenToMessages(room,
message => {
let sender = keys[message.sender];
let recipient = message.recipient && keys[message.recipient];
if (message.publicKey) {
if (sender) return;
PgpKey.load(message.publicKey, key => {
let isMyKey = myKey.id() === key.id();
keys[key.id()] = isMyKey ? myKey : key;
renderMessage(key.nickname() + ' joined', '');
if (!isMyKey)
chatApi.sendMessage(room, {sender: myKey.id(), publicKey: myKey.public()});
});
} else if (sender && recipient && recipient.canDecrypt()) {
recipient.decrypt(message.text, text =>
renderMessage(sender.nickname(), text));
}
},
() => chatApi.sendMessage(room, {sender: myKey.id(), publicKey: myKey.public()}));
document.querySelector('.chat').classList.remove('hidden');
newMessage.select();
function renderMessage(from, message) {
let messageEl = createElement('message', message);
messageEl.prepend(createElement('from', from));
logs.append(messageEl);
logs.scrollTop = logs.scrollHeight;
}
}
function createElement(className, text) {
let el = document.createElement("div");
el.classList.add(className);
el.innerText = text || '';
return el;
}
</script>

@ -29,5 +29,3 @@
</form>
</div>
{% endif %}
{% include "layouts/components/message/decryptor.html" %}

Loading…
Cancel
Save