|
@@ -73292,6 +73292,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|
|
const UNDECIDED = 0;
|
|
|
const TRUSTED = 1;
|
|
|
const UNTRUSTED = -1;
|
|
|
+ const TAG_LENGTH = 128;
|
|
|
+ const KEY_ALGO = {
|
|
|
+ 'name': "AES-GCM",
|
|
|
+ 'length': 256
|
|
|
+ };
|
|
|
|
|
|
function parseBundle(bundle_el) {
|
|
|
/* Given an XML element representing a user's OMEMO bundle, parse it
|
|
@@ -73396,25 +73401,23 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|
|
};
|
|
|
},
|
|
|
|
|
|
- decryptMessage(key_and_tag, attrs) {
|
|
|
- const aes_data = this.getKeyAndTag(u.arrayBufferToString(key_and_tag));
|
|
|
- const CryptoKeyObject = {
|
|
|
+ decryptMessage(obj) {
|
|
|
+ const _converse = this.__super__._converse,
|
|
|
+ key_obj = {
|
|
|
"alg": "A256GCM",
|
|
|
"ext": true,
|
|
|
- "k": aes_data.key,
|
|
|
+ "k": obj.key,
|
|
|
"key_ops": ["encrypt", "decrypt"],
|
|
|
"kty": "oct"
|
|
|
};
|
|
|
- return crypto.subtle.importKey('jwk', CryptoKeyObject, 'AES-GCM', true, ['encrypt', 'decrypt']).then(key_obj => {
|
|
|
- return window.crypto.subtle.decrypt({
|
|
|
+ return crypto.subtle.importKey('jwk', key_obj, KEY_ALGO, true, ['encrypt', 'decrypt']).then(key_obj => {
|
|
|
+ const algo = {
|
|
|
'name': "AES-GCM",
|
|
|
- 'iv': u.base64ToArrayBuffer(attrs.iv),
|
|
|
- 'tagLength': 128
|
|
|
- }, key_obj, u.stringToArrayBuffer(attrs.payload));
|
|
|
- }).then(out => {
|
|
|
- const decoder = new TextDecoder();
|
|
|
- return decoder.decode(out);
|
|
|
- });
|
|
|
+ 'iv': u.base64ToArrayBuffer(obj.iv),
|
|
|
+ 'tagLength': TAG_LENGTH
|
|
|
+ };
|
|
|
+ return window.crypto.subtle.decrypt(algo, key_obj, u.base64ToArrayBuffer(obj.payload));
|
|
|
+ }).then(out => new TextDecoder().decode(out)).catch(e => _converse.log(e.toString(), Strophe.LogLevel.ERROR));
|
|
|
},
|
|
|
|
|
|
decrypt(attrs) {
|
|
@@ -73455,7 +73458,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|
|
const address = new libsignal.SignalProtocolAddress(attrs.from, attrs.encrypted.device_id),
|
|
|
session_cipher = new window.libsignal.SessionCipher(_converse.omemo_store, address),
|
|
|
libsignal_payload = JSON.parse(atob(attrs.encrypted.key));
|
|
|
- session_cipher.decryptPreKeyWhisperMessage(libsignal_payload.body, 'binary').then(key_and_tag => this.decryptMessage(key_and_tag, attrs.encrypted)).then(f => {
|
|
|
+ session_cipher.decryptPreKeyWhisperMessage(libsignal_payload.body, 'binary').then(key_and_tag => this.decryptMessage(attrs.encrypted)).then(f => {
|
|
|
// TODO handle new key...
|
|
|
// _converse.omemo.publishBundle()
|
|
|
resolve(f);
|
|
@@ -73490,13 +73493,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|
|
encryptMessage(plaintext) {
|
|
|
// The client MUST use fresh, randomly generated key/IV pairs
|
|
|
// with AES-128 in Galois/Counter Mode (GCM).
|
|
|
- const TAG_LENGTH = 128,
|
|
|
- iv = window.crypto.getRandomValues(new window.Uint8Array(16));
|
|
|
+ const iv = window.crypto.getRandomValues(new window.Uint8Array(16));
|
|
|
let key;
|
|
|
- return window.crypto.subtle.generateKey({
|
|
|
- 'name': "AES-GCM",
|
|
|
- 'length': 256
|
|
|
- }, true, // extractable
|
|
|
+ return window.crypto.subtle.generateKey(KEY_ALGO, true, // extractable
|
|
|
["encrypt", "decrypt"] // key usages
|
|
|
).then(result => {
|
|
|
key = result;
|
|
@@ -73509,10 +73508,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|
|
}).then(ciphertext => {
|
|
|
return window.crypto.subtle.exportKey("jwk", key).then(key_obj => {
|
|
|
return Promise.resolve({
|
|
|
- 'key_str': key_obj.k,
|
|
|
- 'tag': btoa(ciphertext.slice(ciphertext.byteLength - (TAG_LENGTH + 7 >> 3))),
|
|
|
- 'ciphertext': btoa(ciphertext),
|
|
|
- 'iv': btoa(iv)
|
|
|
+ 'key': key_obj.k,
|
|
|
+ 'tag': u.arrayBufferToBase64(ciphertext.slice(ciphertext.byteLength - (TAG_LENGTH + 7 >> 3))),
|
|
|
+ 'payload': u.arrayBufferToBase64(ciphertext),
|
|
|
+ 'iv': u.arrayBufferToBase64(iv)
|
|
|
});
|
|
|
});
|
|
|
});
|
|
@@ -73579,15 +73578,15 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|
|
}).c('header', {
|
|
|
'sid': _converse.omemo_store.get('device_id')
|
|
|
});
|
|
|
- return this.encryptMessage(message).then(payload => {
|
|
|
+ return this.encryptMessage(message).then(obj => {
|
|
|
// The 16 bytes key and the GCM authentication tag (The tag
|
|
|
// SHOULD have at least 128 bit) are concatenated and for each
|
|
|
// intended recipient device, i.e. both own devices as well as
|
|
|
// devices associated with the contact, the result of this
|
|
|
// concatenation is encrypted using the corresponding
|
|
|
// long-standing SignalProtocol session.
|
|
|
- const promises = devices.filter(device => device.get('trusted') != UNTRUSTED).map(device => this.encryptKey(payload.key_str + payload.tag, device));
|
|
|
- return Promise.all(promises).then(dicts => this.addKeysToMessageStanza(stanza, dicts, payload.iv)).then(stanza => stanza.c('payload').t(payload.ciphertext)).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
|
|
+ const promises = devices.filter(device => device.get('trusted') != UNTRUSTED).map(device => this.encryptKey(obj.key + obj.tag, device));
|
|
|
+ return Promise.all(promises).then(dicts => this.addKeysToMessageStanza(stanza, dicts, obj.iv)).then(stanza => stanza.c('payload').t(obj.payload)).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
|
|
});
|
|
|
},
|
|
|
|