converse.js
converse.js copied to clipboard
"Error: Identity key changed" when sending a second OMEMO message
- You click on "lock" icon
- Send message to User 1
- Open other browser where you have loggedin User 1
- You click on "lock" icon.
- Send message to User 0
- Try to send another and you got:
Sorry, could not send the message due to an error. Identity key changed
- You logout and try again, it is the same (all the time I have unchecked
This is a trusted device
) I am trying this all day and every time it is the same. I used latestlibsignal-protocol.js
.

So as far as i can see Omemo does not work on converse.js. Hwo to debug this to checkout why?
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
In src/converse-omemo.js line 566:
const trusted = this.get('identity_key'+identifier);
console.log("-------------------------------------------------------------------------------------");
console.log(identifier); --> jid of user that I am trying to send message
console.log(identity_key); --> ArrayBuffer
console.log(trusted); -> this is empty
console.log(u.arrayBufferToBase64(identity_key)) this is correct with some value
console.log("-------------------------------------------------------------------------------------");
Further more: Line 567:
if (trusted === undefined) {
return Promise.resolve(true);
}
If i change to:
if (trusted === undefined || trusted === "") {
return Promise.resolve(true);
}
messages are encrypted (i can see that i jabber log).
So I am not really sure if this is the right way to solve this? I would really appreciate some comment @jcbrand .
So are you saying that checking for trusted === ""
fixes the problem?
If so then the problem seems to be (in part at least) that an identify key with an empty string as value had been saved, which is why your change seems to fix it.
The question now is why it got that value in the first place and whether we should be concerned about it.
What browser are you using?
Also, could you please check what happens when saveIdentity is called and whether the values look correct there? Specifically important to know is whether a proper value (i.e. not ""
) gets saved and whether it gets saved under the same key (i.e. whether 'identity_key'+address.getName()
in saveIdentity
is the same as 'identity_key'+identifier
in isTrustedIdentity
).
console.log("-----------------------------------------------------------")
console.log(identifier) --> [email protected]
console.log(address) --> libsignal.SignalProtocolAddress {getName: ƒ, getDeviceId: ƒ, toString: ƒ, equals: ƒ}
console.log('identity_key'+address.getName()) --> identity_keychrome@localhost
console.log(existing) --> ""
console.log(u.arrayBufferToBase64(identity_key)) --> ""
console.log("-----------------------------------------------------------")
if (existing && b64_idkey !== existing)
is always false
.
I am using Version 69.0.3497.100 (Official Build) (64-bit)
on
Description: Debian GNU/Linux 9.5 (stretch)
Release: 9.5
Codename: stretch
You logout and try again, it is the same (all the time I have unchecked This is a trusted device )
I think this might be causing the issue here. At least in part.
It doesn't really make sense to try and use OMEMO when that box is unchecked.
An established OMEMO (libsignal) session is supposed to be permanent, which means that it needs to get stored somewhere when you log out. However when the "This is a trusted device" checkbox is unchecked, then your storage gets cleared when you log out.
This means you'll never be able to decrypt messages from before you logged in.
Additionally, OMEMO establishes dependencies between different stores in localStorage and sessionStorage. When first running as a trusted device, and then as an untrusted device, the stores get mixed up and I get invalid signature
errors.
There are ways to fix this, for example by clearing all browser storage before logging in when "This is an untrusted device" is unchecked, or by giving all the stores different root keys.
However, simplest is just to disable OMEMO entirely when that checkbox is unchecked (done in https://github.com/conversejs/converse.js/commit/c8dc7b63b206f8788764650ebce402fc978534c2), which in any case makes sense given the first point raised.
I'm not sure if I should create another issue or post here but I have the exact same problem as stated in this issue: only first message can be sent encrypted and afterwards input box gets grey and "Identity key changed." error occurs. What I have to add is that I am using auto-login setup and "trusted" property is set to true all the time. Here is the initialize call:
converse.initialize({
allow_logout: false,
keepalive: true,
authentication: "login",
auto_login: true,
jid: jid,
password: password,
websocket_url: 'wss://example:5443/ws',
show_controlbox_by_default: true,
show_client_info: false,
trusted: true
});
Could it maybe be wrong configuration of XMPP server (latest version of ejabberd) or maybe it's connected to the fact that this is being tested locally and self-signed certificates are being used or is it something entirely else?
@Bajchos you're on Converse 5.0.1 right?
@licaon-kter Yep, I am using Converse 5.0.1, although this issue was happening on 4.2.0 and 5.0.0 as well.
@Bajchos Are you using your browser in incognito mode?
@jcbrand Actually I tried both normal and incognito mode (Chrome and Firefox), tried also with clearing session and local storage, nothing helped. One more interesting thing: only first ever message gets encrypted, after this only deleting and re-creating users on ejabberd put me to state where this first message can be sent encrypted again (re-login, clearing browser data doesn't help).
@Bajchos: Can you please register an account conversejs.org (you can only do so on https://conversejs.org through Converse.js itself which runs there) and then check whether you can reproduce this issue on that XMPP server?
@jcbrand I couldn't really reproduce the issue on https://conversejs.org, only issue that seemed to look like the one I am having was when I switched 1 user from one browser to another and kept second user logged in and continued to send encrypted messages. I was playing with configuration of XMPP and what seems (need more testing) to solve my problem is changing virtual host (jid of users as well) to match the domain of jabber server. For example:
- my jabber server is hosted on foo.bar.net
- created virtual host named foo.bar.net -> now users' jid is [email protected]
- previously virtual host was name foo -> users' jid was user@foo (this way omemo wasn't working) No other changes were done on server side except creating another virtual host and 2 new users under it. No idea if this was the issue but right now I can send encrypted messages between users. 😄
I gave up on conversejs and wrote my own client.
I get Uncaught (in promise) Error: Identity key changed
after sending one encrypted message.
I use the same browser (Chrome) for two users (just changing via logout and login).
After the login I can send one message, before the error is shown in the console and the input field is disabled.
Used scripts: https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js https://cdn.conversejs.org/dist/converse.min.js
Any update on this issue @jcbrand
@nikita-cerejo you are seeing this issue with latest 8 release or git HEAD code?
I faced this issue on v8.0.2dev Whenever I click on lock icon and send message to a contact, it gives me error as identity key changed and also message box greys out like disabled. But if I again click on lock icon, and try sending unencrypted message, the message box enables and I am able to send message.
@nikita-cerejo: Where/how are you using Converse?
The latest version can be tested here: https://conversejs.org/trunk/fullscreen.html
Can you reproduce the issue there?
I am using github conversejs master branch, downloading the zip and using it via docker on localhost.
@nikita-cerejo: So you're building Converse yourself with make dist
?
Can you please update the HTML file you're using (I'm guessing fullscreen.html
) to use converse.js and not converse.min.js.
That way we'll get usable line numbers in error tracebacks.
Then check your browser console for errors and post it here. Thanks.
Yes I have replaced fullscreen.html
3 days ago. There were few fixes in conversejs master so you had suggested me before to replace it. And also changed converse.min.js to converse.js.
The libsignal-protocol.min.js cdn used is :
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
Below is the screenshot of the error I am getting.
Please use the unminified version of libsignal as well (libsignal-protocol.js
).
https://conversejs.org/3rdparty/libsignal-protocol.js
Then, when you get the error, please click on the red triangle (just before Uncaught
) to open it up, so that the whole traceback can be seen.
Here is the screenshot of using unminified version and error traceback
@jcbrand I tried the same with v9.0.0 still getting the same error. Let me know if any more information needed.
@jcbrand Were you able to regenerate this issue at your end? Any update on it?
No, I haven't reproduced it. I've mainly been looking at the code based on the traceback you've sent.
Have you read this comment? https://github.com/conversejs/converse.js/issues/1242#issuecomment-521997403 Based on that comment, I wonder whether this has to do with you hosting your XMPP server locally (and how you're doing it).
Please set loglevel
to 'debug'
when calling converse.initialize
and then set logging to "verbose" in your browser console. Then reproduce the bug, save the console log output to a file and either paste it here or email it to me.
Maybe there's something in there that shows what's going on.
If that doesn't work, we can try to schedule a video call some time.
Thanks @jcbrand I am able to send encrypted messages when I changed my virtualhost domain from localhost
to server.localhost
. But I faced a scenario in this, which gives error that contact client doesn't support omemo encryption. As shown in below screenshot(A).
Scenario :
-> For the first time when contact is added, if user A (in my case Test 1 i.e [email protected]) sent contact request to user B (in my case Test 4 i.e [email protected]) and user B accepts it.
-> If user B tries to send encrypted message first, it gives error that omemo encryption is not supported by user A client.
-> But if user A sends encrypted message to user B first and then user B sends encrypted message then it works properly as shown in the screenshot(B).
(Note : Test1 was logged in from chrome and Test 4 was logged in from microsoft edge browser)
screenshot(A) :
screenshot(B) :
@nikita-cerejo: Ok, that sounds like a different issue. Can you please create a new issue for this? You can just copy/paste the same data from this comment into it.
Sounds to me like Converse should be fetching the OMEMO bundle for user A, but isn't.