Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
1d5cf8eb
Commit
1d5cf8eb
authored
Aug 31, 2018
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix AES-GCM encryption/decryption so that it works with Conversations
Fixes #497
parent
dd71d6ee
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
57 additions
and
67 deletions
+57
-67
dist/converse.js
dist/converse.js
+28
-32
src/converse-omemo.js
src/converse-omemo.js
+29
-35
No files found.
dist/converse.js
View file @
1d5cf8eb
...
...
@@ -71570,7 +71570,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
/* global libsignal, ArrayBuffer, parseInt */
/* global libsignal, ArrayBuffer, parseInt
, crypto
*/
(function (root, factory) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! templates/toolbar_omemo.html */ "./src/templates/toolbar_omemo.html")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
...
...
@@ -71769,6 +71769,29 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
});
},
async encryptMessage(plaintext) {
// The client MUST use fresh, randomly generated key/IV pairs
// with AES-128 in Galois/Counter Mode (GCM).
const iv = crypto.getRandomValues(new window.Uint8Array(16));
const key = await crypto.subtle.generateKey(KEY_ALGO, true, ["encrypt", "decrypt"]);
const algo = {
'name': 'AES-GCM',
'iv': iv,
'tagLength': TAG_LENGTH
};
const encrypted = await crypto.subtle.encrypt(algo, key, u.stringToArrayBuffer(plaintext));
const length = encrypted.byteLength - (128 + 7 >> 3),
ciphertext = encrypted.slice(0, length),
tag = encrypted.slice(length);
const exported_key = await crypto.subtle.exportKey("raw", key);
return Promise.resolve({
'key': key,
'key_and_tag': u.appendArrayBuffer(exported_key, tag),
'payload': u.arrayBufferToBase64(ciphertext),
'iv': u.arrayBufferToBase64(iv)
});
},
decryptMessage(obj) {
return crypto.subtle.importKey('raw', obj.key, KEY_ALGO, true, ['encrypt', 'decrypt']).then(key_obj => {
const algo = {
...
...
@@ -71776,15 +71799,16 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'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));
const cipher = u.appendArrayBuffer(u.base64ToArrayBuffer(obj.payload), obj.tag);
return crypto.subtle.decrypt(algo, key_obj, cipher);
}).then(out => u.arrayBufferToString(out));
},
reportDecryptionError(e) {
const _converse = this.__super__._converse,
__ = _converse.__;
this.messages.create({
'message': __("Sorry, could not decrypt a received OMEMO message due to an error.") + `${e.name} ${e.message}`,
'message': __("Sorry, could not decrypt a received OMEMO message due to an error.") + `
${e.name} ${e.message}`,
'type': 'error'
});
...
...
@@ -71879,34 +71903,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
return Promise.all(devices.map(device => this.getSession(device))).then(() => devices);
},
encryptMessage(plaintext) {
// The client MUST use fresh, randomly generated key/IV pairs
// with AES-128 in Galois/Counter Mode (GCM).
const iv = window.crypto.getRandomValues(new window.Uint8Array(16));
let key;
return window.crypto.subtle.generateKey(KEY_ALGO, true, // extractable
["encrypt", "decrypt"] // key usages
).then(result => {
key = result;
const algo = {
'name': 'AES-GCM',
'iv': iv,
'tagLength': TAG_LENGTH
};
return window.crypto.subtle.encrypt(algo, key, new TextEncoder().encode(plaintext));
}).then(ciphertext => {
return window.crypto.subtle.exportKey("raw", key).then(key => {
const tag = ciphertext.slice(ciphertext.byteLength - (TAG_LENGTH + 7 >> 3));
return Promise.resolve({
'key': key,
'key_and_tag': u.appendArrayBuffer(key, tag),
'payload': u.arrayBufferToBase64(ciphertext),
'iv': u.arrayBufferToBase64(iv)
});
});
});
},
getSessionCipher(jid, id) {
const _converse = this.__super__._converse,
address = new libsignal.SignalProtocolAddress(jid, id);
src/converse-omemo.js
View file @
1d5cf8eb
...
...
@@ -4,7 +4,7 @@
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
/* global libsignal, ArrayBuffer, parseInt */
/* global libsignal, ArrayBuffer, parseInt
, crypto
*/
(
function
(
root
,
factory
)
{
define
([
...
...
@@ -201,6 +201,30 @@
});
},
async
encryptMessage
(
plaintext
)
{
// The client MUST use fresh, randomly generated key/IV pairs
// with AES-128 in Galois/Counter Mode (GCM).
const
iv
=
crypto
.
getRandomValues
(
new
window
.
Uint8Array
(
16
));
const
key
=
await
crypto
.
subtle
.
generateKey
(
KEY_ALGO
,
true
,
[
"
encrypt
"
,
"
decrypt
"
]);
const
algo
=
{
'
name
'
:
'
AES-GCM
'
,
'
iv
'
:
iv
,
'
tagLength
'
:
TAG_LENGTH
}
const
encrypted
=
await
crypto
.
subtle
.
encrypt
(
algo
,
key
,
u
.
stringToArrayBuffer
(
plaintext
));
const
length
=
encrypted
.
byteLength
-
((
128
+
7
)
>>
3
),
ciphertext
=
encrypted
.
slice
(
0
,
length
),
tag
=
encrypted
.
slice
(
length
);
const
exported_key
=
await
crypto
.
subtle
.
exportKey
(
"
raw
"
,
key
)
return
Promise
.
resolve
({
'
key
'
:
key
,
'
key_and_tag
'
:
u
.
appendArrayBuffer
(
exported_key
,
tag
),
'
payload
'
:
u
.
arrayBufferToBase64
(
ciphertext
),
'
iv
'
:
u
.
arrayBufferToBase64
(
iv
)
});
},
decryptMessage
(
obj
)
{
return
crypto
.
subtle
.
importKey
(
'
raw
'
,
obj
.
key
,
KEY_ALGO
,
true
,
[
'
encrypt
'
,
'
decrypt
'
])
.
then
(
key_obj
=>
{
...
...
@@ -209,15 +233,16 @@
'
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
));
const
cipher
=
u
.
appendArrayBuffer
(
u
.
base64ToArrayBuffer
(
obj
.
payload
),
obj
.
tag
);
return
crypto
.
subtle
.
decrypt
(
algo
,
key_obj
,
cipher
);
}).
then
(
out
=>
u
.
arrayBufferToString
(
out
));
},
reportDecryptionError
(
e
)
{
const
{
_converse
}
=
this
.
__super__
,
{
__
}
=
_converse
;
this
.
messages
.
create
({
'
message
'
:
__
(
"
Sorry, could not decrypt a received OMEMO message due to an error.
"
)
+
`
${
e
.
name
}
${
e
.
message
}
`
,
'
message
'
:
__
(
"
Sorry, could not decrypt a received OMEMO message due to an error.
"
)
+
`
${
e
.
name
}
${
e
.
message
}
`
,
'
type
'
:
'
error
'
,
});
_converse
.
log
(
e
,
Strophe
.
LogLevel
.
ERROR
);
...
...
@@ -300,37 +325,6 @@
return
Promise
.
all
(
devices
.
map
(
device
=>
this
.
getSession
(
device
))).
then
(()
=>
devices
);
},
encryptMessage
(
plaintext
)
{
// The client MUST use fresh, randomly generated key/IV pairs
// with AES-128 in Galois/Counter Mode (GCM).
const
iv
=
window
.
crypto
.
getRandomValues
(
new
window
.
Uint8Array
(
16
));
let
key
;
return
window
.
crypto
.
subtle
.
generateKey
(
KEY_ALGO
,
true
,
// extractable
[
"
encrypt
"
,
"
decrypt
"
]
// key usages
).
then
(
result
=>
{
key
=
result
;
const
algo
=
{
'
name
'
:
'
AES-GCM
'
,
'
iv
'
:
iv
,
'
tagLength
'
:
TAG_LENGTH
}
return
window
.
crypto
.
subtle
.
encrypt
(
algo
,
key
,
new
TextEncoder
().
encode
(
plaintext
));
}).
then
(
ciphertext
=>
{
return
window
.
crypto
.
subtle
.
exportKey
(
"
raw
"
,
key
)
.
then
(
key
=>
{
const
tag
=
ciphertext
.
slice
(
ciphertext
.
byteLength
-
((
TAG_LENGTH
+
7
)
>>
3
));
return
Promise
.
resolve
({
'
key
'
:
key
,
'
key_and_tag
'
:
u
.
appendArrayBuffer
(
key
,
tag
),
'
payload
'
:
u
.
arrayBufferToBase64
(
ciphertext
),
'
iv
'
:
u
.
arrayBufferToBase64
(
iv
)
});
});
});
},
getSessionCipher
(
jid
,
id
)
{
const
{
_converse
}
=
this
.
__super__
,
address
=
new
libsignal
.
SignalProtocolAddress
(
jid
,
id
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment