Commit 3eb5e93f authored by JC Brand's avatar JC Brand

Finally able to send a message and decrypt it on the other side

Updates #497
parent 2dd5976f
...@@ -551,8 +551,8 @@ ...@@ -551,8 +551,8 @@
} }
} }
const result = this.getMessageAttributesFromStanza(message, original_stanza) const result = this.getMessageAttributesFromStanza(message, original_stanza)
if (result instanceof Promise) { if (typeof result.then === "function") {
return new Promise((resolve, reject) => result.then(attrs => resolve(_create(attrs))).catch(reject)); return new Promise((resolve, reject) => result.then(attrs => resolve(_create(attrs))));
} else { } else {
const message = _create(result) const message = _create(result)
return Promise.resolve(message); return Promise.resolve(message);
......
...@@ -228,16 +228,11 @@ ...@@ -228,16 +228,11 @@
}).then(out => (new TextDecoder()).decode(out)); }).then(out => (new TextDecoder()).decode(out));
}, },
decryptFromKeyAndTag (key_and_tag, obj) {
const aes_data = this.getKeyAndTag(u.arrayBufferToString(key_and_tag));
return this.decryptMessage(_.extend(obj, {'key': aes_data.key, 'tag': aes_data.tag}));
},
reportDecryptionError (e) { reportDecryptionError (e) {
const { _converse } = this.__super__, const { _converse } = this.__super__,
{ __ } = _converse; { __ } = _converse;
this.messages.create({ this.messages.create({
'message': __("Sorry, could not decrypt a received OMEMO message due to an error.") + ` ${e.message}`, 'message': __("Sorry, could not decrypt a received OMEMO message due to an error.") + `${e.name} ${e.message}`,
'type': 'error', 'type': 'error',
}); });
_converse.log(e, Strophe.LogLevel.ERROR); _converse.log(e, Strophe.LogLevel.ERROR);
...@@ -260,34 +255,28 @@ ...@@ -260,34 +255,28 @@
// that it won't be used again by a different client. If the client already has a session // that it won't be used again by a different client. If the client already has a session
// with the sender's device, it MUST replace this session with the newly built session. // with the sender's device, it MUST replace this session with the newly built session.
// The client MUST delete the private key belonging to the PreKey after use. // The client MUST delete the private key belonging to the PreKey after use.
//
// TODO: republish bundle information with old prekey removed and with new prekey
// TODO: The client MUST delete the private key belonging to the PreKey after use.
return session_cipher.decryptPreKeyWhisperMessage(libsignal_payload.body, 'binary') return session_cipher.decryptPreKeyWhisperMessage(libsignal_payload.body, 'binary')
.then(key_and_tag => { .then(key_and_tag => {
debugger; const aes_data = this.getKeyAndTag(u.arrayBufferToString(key_and_tag));
return this.decryptFromKeyAndTag(key_and_tag, attrs.encrypted) return this.decryptMessage(_.extend(attrs.encrypted, {'key': aes_data.key, 'tag': aes_data.tag}));
}) }).then(plaintext => {
.then((f) => { // TODO remove newly used key before republishing
debugger;
// TODO remove newly used key before
// republishing
_converse.omemo.publishBundle() _converse.omemo.publishBundle()
}) return _.extend(attrs, {'plaintext': plaintext});
.catch((e) => { }).catch((e) => {
debugger;
this.reportDecryptionError(e); this.reportDecryptionError(e);
return Promise.resolve(attrs); return attrs;
}); });
} else { } else {
return session_cipher.decryptWhisperMessage(libsignal_payload.body, 'binary') return session_cipher.decryptWhisperMessage(libsignal_payload.body, 'binary')
.then(key_and_tag => this.decryptFromKeyAndTag(key_and_tag, attrs.encrypted)) .then(key_and_tag => {
.then(plaintext => _.extend(attrs, {'plaintext': plaintext})) const aes_data = this.getKeyAndTag(u.arrayBufferToString(key_and_tag));
.catch((e) => { return this.decryptMessage(_.extend(attrs.encrypted, {'key': aes_data.key, 'tag': aes_data.tag}));
debugger; }).then(plaintext => _.extend(attrs, {'plaintext': plaintext}))
this.reportDecryptionError(e); .catch((e) => {
return Promise.resolve(attrs); this.reportDecryptionError(e);
}); return attrs;
});
} }
}, },
...@@ -341,16 +330,14 @@ ...@@ -341,16 +330,14 @@
'tagLength': TAG_LENGTH 'tagLength': TAG_LENGTH
} }
return window.crypto.subtle.encrypt(algo, key, new TextEncoder().encode(plaintext)); return window.crypto.subtle.encrypt(algo, key, new TextEncoder().encode(plaintext));
}).then((ciphertext) => { }).then(ciphertext => {
return window.crypto.subtle.exportKey("jwk", key) return window.crypto.subtle.exportKey("jwk", key)
.then((key_obj) => { .then(key_obj => {
const tag = u.arrayBufferToBase64(ciphertext.slice(ciphertext.byteLength - ((TAG_LENGTH + 7) >> 3))); const tag = u.arrayBufferToBase64(ciphertext.slice(ciphertext.byteLength - ((TAG_LENGTH + 7) >> 3)));
console.log('XXXX: Base64 TAG is '+tag);
console.log('YYY: KEY is '+key_obj.k);
return Promise.resolve({ return Promise.resolve({
'key': key_obj.k, 'key': key_obj.k,
'tag': tag, 'tag': tag,
'key_and_tag': btoa(key_obj.k + tag), 'key_and_tag': key_obj.k + tag,
'payload': u.arrayBufferToBase64(ciphertext), 'payload': u.arrayBufferToBase64(ciphertext),
'iv': u.arrayBufferToBase64(iv) 'iv': u.arrayBufferToBase64(iv)
}); });
...@@ -391,6 +378,9 @@ ...@@ -391,6 +378,9 @@
const body = __("This is an OMEMO encrypted message which your client doesn’t seem to support. "+ const body = __("This is an OMEMO encrypted message which your client doesn’t seem to support. "+
"Find more information on https://conversations.im/omemo"); "Find more information on https://conversations.im/omemo");
if (!message.get('message')) {
throw new Error("No message body to encrypt!");
}
const stanza = $msg({ const stanza = $msg({
'from': _converse.connection.jid, 'from': _converse.connection.jid,
'to': this.get('jid'), 'to': this.get('jid'),
...@@ -406,7 +396,7 @@ ...@@ -406,7 +396,7 @@
.c('encrypted', {'xmlns': Strophe.NS.OMEMO}) .c('encrypted', {'xmlns': Strophe.NS.OMEMO})
.c('header', {'sid': _converse.omemo_store.get('device_id')}); .c('header', {'sid': _converse.omemo_store.get('device_id')});
return this.encryptMessage(message).then(obj => { return this.encryptMessage(message.get('message')).then(obj => {
// The 16 bytes key and the GCM authentication tag (The tag // The 16 bytes key and the GCM authentication tag (The tag
// SHOULD have at least 128 bit) are concatenated and for each // SHOULD have at least 128 bit) are concatenated and for each
// intended recipient device, i.e. both own devices as well as // intended recipient device, i.e. both own devices as well as
...@@ -426,7 +416,8 @@ ...@@ -426,7 +416,8 @@
sendMessage (attrs) { sendMessage (attrs) {
const { _converse } = this.__super__, const { _converse } = this.__super__,
{ __ } = _converse; { __ } = _converse;
if (this.get('omemo_active')) {
if (this.get('omemo_active') && attrs.message) {
const message = this.messages.create(attrs); const message = this.messages.create(attrs);
this.getBundlesAndBuildSessions() this.getBundlesAndBuildSessions()
.then(devices => this.createOMEMOMessageStanza(message, devices)) .then(devices => this.createOMEMOMessageStanza(message, devices))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment