-
-
Notifications
You must be signed in to change notification settings - Fork 595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to enable encryption? #731
Comments
I have similar problems, so let me try to help you and text back, if you got it working.
|
Great news, I was waiting for some help for a long time, thanks already so much, I will try it on the weekend! |
depending on your build system you may need |
(1) We can now read encrypted messages. It turns out that we should wait a little bit more to ensure crypto is initialized correctly. (matrix-org/matrix-js-sdk#731) (2) We still need to claim keys every time we refresh the page. This should be fixed later. (3) We cannot send encrypted messages yet. This should be fixed later. (4) Verifying devices is not yet supported.
So I have tried it again and the encryption seems to be initialized ok but the messages arrive unencryped. Here is what I did. Anybody up for a helping hand?
|
If you don't call & await |
Thanks @t3chguy
I get the following messages on the shell
|
Ok I tried the following, still no success
|
I think i'm a bit closer now. The problem was
Is there a way to tell the client to ignore that |
YESSS I finally figured it out. This is a working minimal example of how to send an encrypted message with the js-sdk. It runs on node and you will need to install the following dependencies (choose your olm version here):
#!/usr/bin/env node
const sdk = require('matrix-js-sdk');
global.Olm = require('olm');
const { LocalStorage } = require('node-localstorage');
const localStorage = new LocalStorage('./scratch');
const {
LocalStorageCryptoStore,
} = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
const channel = '!XXXXXXXXXXXX:matrix.org';
const message = 'hello world e2e encrypted';
const client = sdk.createClient({
baseUrl: `https://matrix.org`,
accessToken: 'XXXXXXXXXXXX',
sessionStore: new sdk.WebStorageSessionStore(localStorage),
cryptoStore: new LocalStorageCryptoStore(localStorage),
userId: '@XXXXXXXXXXXX:matrix.org',
deviceId: 'XXXXXXXXXXXX',
});
client.on('sync', function (state) {
if (state !== 'PREPARED') return;
client.setGlobalErrorOnUnknownDevices(false);
client
.joinRoom(channel)
.then(() =>
client.sendEvent(
channel,
'm.room.message',
{
msgtype: 'm.text',
format: 'org.matrix.custom.html',
body: message,
formatted_body: message,
},
''
)
)
.then(() => {
process.exit(0);
})
.catch((err) => {
console.error('err', err);
});
});
client
.initCrypto()
.then(() => client.startClient({ initialSyncLimit: 1 }))
.catch((err) => {
console.error('err', err);
}); ... only took me 2 years :P |
ES5 version #!/usr/bin/env node
const sdk = require('matrix-js-sdk');
global.Olm = require('olm');
const { LocalStorage } = require('node-localstorage');
const localStorage = new LocalStorage('./scratch');
const {
LocalStorageCryptoStore,
} = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
const channel = '!XXXXXXXXXXXX:matrix.org';
const message = 'hello world e2e encrypted';
const client = sdk.createClient({
baseUrl: `https://matrix.org`,
accessToken: 'XXXXXXXXXXXX',
sessionStore: new sdk.WebStorageSessionStore(localStorage),
cryptoStore: new LocalStorageCryptoStore(localStorage),
userId: '@XXXXXXXXXXXX:matrix.org',
deviceId: 'XXXXXXXXXXXX',
});
client.on('sync', async function (state, prevState, res) {
if (state !== 'PREPARED') return;
client.setGlobalErrorOnUnknownDevices(false);
await client.joinRoom(channel);
await client.sendEvent(
channel,
'm.room.message',
{
msgtype: messagetype,
format: 'org.matrix.custom.html',
body: message,
formatted_body: message,
},
''
);
process.exit(0);
});
async function run() {
await client.initCrypto();
await client.startClient({ initialSyncLimit: 1 });
}
run().catch((error) => console.error(error)); |
To read encrypted messages I found this to be working client.on('Room.timeline', async (message, room) => {
if (!isReady) return;
let body = '';
try {
if (message.event.type === 'm.room.encrypted') {
const event = await client._crypto.decryptEvent(message);
({ body } = event.clearEvent.content);
} else {
({ body } = message.event.content);
}
if (body) {
// do something
}
} catch (error) {
console.error('#### ', error);
}
}); |
Hi select, and thank you for posting your findings, strange that this is the only really useful resource on getting encryption to work in the Matrix SDK that i've been able to find. A quick question, i've done what you suggested, but I am getting this error in an encrypted room, did this happen to you, and if so, how did you handle it?
It would seem like I need to do something more than just enabling encryption, to actually be able to decrypt messages. |
I recently encountered this useful issue(#731) while looking for how to implement OLM in an application for a user living on a homeserver that requires e2ee. The logging becomes really detailed after There's a particular line in one of the code blocks above, which I found really useful while testing: client.setGlobalErrorOnUnknownDevices(false) I think this might also be what the Element client uses, basically w/o it, OLM will throw if there's unverified sessions in the room. |
did you wait until the client is ready? |
@select Yes, communication in non-encrypted rooms work fine. I've been trying for a couple hours today, and have simply not been able to get anything to work (using sdk v9.7.0), so i've put encryption to the side for a bit, and I think that I will use pantalaimon for encryption if the need arises in the future. To me, it doesn't seem like the SDK is really ready to handle encryption fully just yet. |
@FlyveHest have a look here, I have just published a working version of a bot that can read and send e2e messages https://gitlab.com/s3lect/taavi-bot It uses the sdk v9.7.0 |
@select Interesting, the part of your code that implements the Matrix connectivity is more or less the exact same I had used (not a big surprise, as I used the code you posted above :), but, you have included the olm.js as a file directly in your project, and I added it as an NPM package. I'll try and clone your repo and see if I can get it to work on my server, it might not be related to the code, but maybe that I have to import / identify keys for my BOT account. Edit: Tried it, and it works, sort of, it can't verify a session when I log into Element with the same account, but encrypting the channel does work and it can read the messages posted after the channel has been encrypted. Thanks a lot for the link, i'll try and take a look and see where what I did differ from your implementation. |
@FlyveHest what I found was that olm is not distributed with npm anymore, I could not find a reason though.
|
@FlyveHest I was also able to (eventually) get e2e working, although there definitely were some peculiarities and hoops to jump through. Feel free to take a look at my implementation here: https://github.com/zhaytee/matrix-rpc-bot |
@zhaytee @select Thanks you both, I got e2e working in my BOT implementation as well, the key point I was missing to begin with was that I did not save the device ID from the initial login, apparantly, when I did that, everything seemed to click. Its hard to say whats best practice here, but I like the way @zhaytee handles the decryption a bit better than manually decrypting it, but that process is not described anywhere in the docs (at least, none that I could find), so kudos for the digging work there, it helped a lot. (And, on a sidenote, what I am aiming at is not that different from your project, its just not using gRPC) |
@FlyveHest Can you share your implementation please? I'm facing the same issue. Honestly, I don't know what device ID is. Do you know what it is? Thanks |
@Myzel394 you get a device id when you create the login credentials. getCredentialsWithPassword(username, password) {
return new Promise(resolve => {
Matrix.createClient('https://matrix.org')
.loginWithPassword(username, password)
.then(credentials => {
resolve({
accessToken: credentials.access_token,
userId: credentials.user_id,
deviceId: credentials.device_id,
});
});
});
},
``` |
How do I decrypt a received file? I got the message decrypted and the mxc url converted but when the file is downloaded it is clearly encypted. I see the |
I wanted to come back and leave this for anyone else that wants to encrypt/decrypt files. There is a repo that has an example on how to do just this: I had to modify it a little bit to get it to work in my project but it pointed me in the right direction. |
@zhaytee @FlyveHest any chance to share the code of how it should be done the right way? unfortunately, @zhaytee's repository does no longer exist and I would like to see how he has done it... any help would be appreciated! |
Instead of doing: matrixClient.crypto.decryptEvent(ev).then(encryptedEvent => {
const { type, content } = encryptedEvent.clearEvent;
console.error('----->', { type, content });
}); it should be done this way: await matricClient.decryptEventIfNeeded(ev);
console.error('--->', ev.getContent()); |
@trancee Hey, how's it going? Did you manage to get how to send and receive encrypted files? |
@AbdullahQureshi1080 I got sending and receiving encrypted files working in encrypted rooms. |
@Electrofenster That's awesome. I have been working on making the whole encryption system work with the js sdk using react native clients. I have had some success but there are issues with backups. Currently working on the sending/receiving encrypted attachments. Is there a example project that you can share? Also would be awesome if you can help with these issues. |
@AbdullahQureshi1080 do you have a SessionStorage? If no, you may need to implement an own SessionStorage to handle the required actions (see matrix-js-sdk). I recommended react-native-mmkv for storing data, it's very fast and stores the data betweeen restarts which is required. With a right setup I think you can fix your most problems. |
Well I use the session store that matrix creates itself and it works fine up until I delete the stores or delete the app and then when I try to restore the backups it does get the backup but invalidates the signature. Not sure what happens over there. |
@AbdullahQureshi1080 well, that's a problem. As I remember, the store from matrix uses for crypto store and session store the indexeddb-backend which is not available in react-native. |
Hmm, I see. But how to setup the crypto and session store? I tried to using a async crypto store that used react-native-async-storage but it does not work. Can you help me out in setting both the stores in client initialization? As you suggested if you can let me know how to initialize the stores properly with the right methods that exists I can use react-native-mmkv. |
@AbdullahQureshi1080 as the react-native-async-storage does not work properly as crpyto-, and session store you'll get a lot of errors when using it. Since there is nothing documented it's very hard to use the right one. I can't provide some code but you can create one like this: import { SessionStore } from 'matrix-js-sdk/src/client';
class MySessionStore implements SessionStore {} now the IDE should suggest you the missing functions you could create. Now you can log in each function the parameter. Just look the indexeddb-storages to understand the logic which you need to implement like your own. The same with the more important crypto store: import { CryptoStore } from 'matrix-js-sdk/src/crypto/store/base';
class MyCryptoStore implements CryptoStore {
public storeEndToEndRoom(roomId: string, roomInfo: IRoomEncryption, txn: any): void {
console.log({ roomId, roomInfo, txn })
}
} |
Will have a go at it. Same with the crypto store? Yes? |
@AbdullahQureshi1080 see my edited answer. Same with crypto store. You'll also need a custom transaction class for crypto store to work. Which "emulates" |
I can understand, been working with matrix for a while now and e2e has a lot of kicks to it that can take time to make things work. Thanks for the pointers 👍🏻 |
@Electrofenster Hey, I looked into the stores. The session store does not exists in the latest SDK version v23.3.0 instead there is a memory-store/local-storage that extends for both storage store and crypto store. I am using this Async Crypto Store as base and added missing methods, updated store is this.
There were still issues with the backup that did not arise earlier, particularly with the backup manager after this new initialization. The backup manager is not being able to upload pending keys for a few sessions. Further debugging led that there is session data missing in a lot of sessions in the crypto stores. |
And... And it doesn't work now.
If delete sessionStore:
|
I am trying to enable encryption in my client and already found out that the example the readme provides is not complete. What i did was the following:
In
package.json
add the following packageIn webpack in the
module
section I disabled the parsing so I would not get the errors about the missing node modulesTo start the server with encryption I have the following code
But when I try to send a message to an encrypted room I get an error
In addition I do not recieve messages and see the following console output
What do I need to do next? I have the feeling I have to find out how to listen to key request and then confirm some keys?
The text was updated successfully, but these errors were encountered: