Skip to content

Commit

Permalink
Merge pull request #142 from turt2live/travis/e2ee
Browse files Browse the repository at this point in the history
Add basic encryption support for simple bots
  • Loading branch information
turt2live authored Aug 17, 2021
2 parents 4054706 + e07b0f4 commit 96bc40d
Show file tree
Hide file tree
Showing 38 changed files with 9,881 additions and 156 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.idea/
lib/
examples/storage/

# Logs
logs
Expand Down
104 changes: 104 additions & 0 deletions examples/encryption_bot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
EncryptionAlgorithm,
FileMessageEventContent,
LogLevel,
LogService,
MatrixClient, MessageEvent,
RichConsoleLogger,
SimpleFsStorageProvider,
} from "../src";
import { SqliteCryptoStorageProvider } from "../src/storage/SqliteCryptoStorageProvider";
import * as fs from "fs";

LogService.setLogger(new RichConsoleLogger());
LogService.setLevel(LogLevel.TRACE);
LogService.muteModule("Metrics");
LogService.trace = LogService.debug;

let creds = null;
try {
creds = require("../../examples/storage/encryption_bot.creds.json");
} catch (e) {
// ignore
}

const dmTarget = creds?.['dmTarget'] ?? "@admin:localhost";
const homeserverUrl = creds?.['homeserverUrl'] ?? "http://localhost:8008";
const accessToken = creds?.['accessToken'] ?? 'YOUR_TOKEN';
const storage = new SimpleFsStorageProvider("./examples/storage/encryption_bot.json");
const crypto = new SqliteCryptoStorageProvider("./examples/storage/encryption_bot.db");
const worksImage = fs.readFileSync("./examples/static/it-works.png");

const client = new MatrixClient(homeserverUrl, accessToken, storage, crypto);

(async function() {
let encryptedRoomId: string;
const joinedRooms = await client.getJoinedRooms();
await client.crypto.prepare(joinedRooms); // init crypto because we're doing things before the client is started
for (const roomId of joinedRooms) {
if (await client.crypto.isRoomEncrypted(roomId)) {
encryptedRoomId = roomId;
break;
}
}
if (!encryptedRoomId) {
encryptedRoomId = await client.createRoom({
invite: [dmTarget],
is_direct: true,
visibility: "private",
preset: "trusted_private_chat",
initial_state: [
{type: "m.room.encryption", state_key: "", content: {algorithm: EncryptionAlgorithm.MegolmV1AesSha2}},
{type: "m.room.guest_access", state_key: "", content: {guest_access: "can_join"}},
],
});
}

client.on("room.failed_decryption", async (roomId: string, event: any, e: Error) => {
LogService.error("index", `Failed to decrypt ${roomId} ${event['event_id']} because `, e);
});

client.on("room.message", async (roomId: string, event: any) => {
if (roomId !== encryptedRoomId) return;

const message = new MessageEvent(event);

if (message.sender === (await client.getUserId()) && message.messageType === "m.notice") {
// yay, we decrypted our own message. Communicate that back for testing purposes.
const encrypted = await client.crypto.encryptMedia(Buffer.from(worksImage));
const mxc = await client.uploadContent(encrypted.buffer);
await client.sendMessage(roomId, {
msgtype: "m.image",
body: "it-works.png",
info: {
// XXX: We know these details, so have hardcoded them.
w: 256,
h: 256,
mimetype: "image/png",
size: worksImage.length,
},
file: {
url: mxc,
...encrypted.file,
},
});
return;
}

if (message.messageType === "m.image") {
const fileEvent = new MessageEvent<FileMessageEventContent>(message.raw);
const decrypted = await client.crypto.decryptMedia(fileEvent.content.file);
fs.writeFileSync('./examples/storage/decrypted.png', decrypted);
await client.unstableApis.addReactionToEvent(roomId, fileEvent.eventId, 'Decrypted');
return;
}

if (message.messageType !== "m.text") return;
if (message.textBody.startsWith("!ping")) {
await client.replyNotice(roomId, event, "Pong");
}
});

LogService.info("index", "Starting bot...");
await client.start();
})();
Binary file added examples/static/it-works.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"test": "ts-mocha --project ./tsconfig.json test/*Test.ts test/**/*.ts",
"build:examples": "tsc -p tsconfig-examples.json",
"example:appservice": "yarn build:examples && node lib/examples/appservice.js",
"example:login_register": "yarn build:examples && node lib/examples/login_register.js"
"example:login_register": "yarn build:examples && node lib/examples/login_register.js",
"example:encryption_bot": "yarn build:examples && node lib/examples/encryption_bot.js"
},
"main": "./lib/index.js",
"typings": "./lib/index.d.ts",
Expand All @@ -47,8 +48,13 @@
"scripts/*",
"tsconfig.json"
],
"optionalDependencies": {
"better-sqlite3": "^7.4.3"
},
"dependencies": {
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.4.tgz",
"@types/express": "^4.17.7",
"another-json": "^0.2.0",
"chalk": "^4.1.0",
"express": "^4.17.1",
"glob-to-regexp": "^0.4.1",
Expand All @@ -64,9 +70,11 @@
"sanitize-html": "^2.3.2"
},
"devDependencies": {
"@types/better-sqlite3": "^5.4.3",
"@types/expect": "^24.3.0",
"@types/mocha": "^8.0.1",
"@types/node": "10",
"@types/simple-mock": "^0.8.2",
"@typescript-eslint/eslint-plugin": "^3.8.0",
"@typescript-eslint/eslint-plugin-tslint": "^3.8.0",
"@typescript-eslint/parser": "^3.8.0",
Expand All @@ -81,6 +89,6 @@
"tmp": "^0.2.1",
"ts-mocha": "^7.0.0",
"tslint": "^6.1.3",
"typescript": "^3.9.7"
"typescript": "^4.3.5"
}
}
Loading

0 comments on commit 96bc40d

Please sign in to comment.