Welcome to our Decentralized Identity (DID) Messaging Application! This chat application leverages the KILT DID key agreement pair for encryption and decryption, as well as the user's authentication key to sign messages. This provides confidence to the receiver in verifying the sender's identity.
For safety and security, it is essential that a user's mnemonic is never shared with other parties. Therefore, for the purposes of this test scenario, we have provided scripts to generate test mnemonics and DIDs. While the application does require the user's mnemonic of their DID to generate the keys necessary for message encryption, decryption, and signing, remember that this mnemonic should be kept confidential and is stored securely in the browser, not kept on the backend server.
To have a look and feel of it we are using the centralized database to store messages, we had plans to intregated with decentralized database solutions but due to time contrains we couldn't do it.
Before you begin the installation, make sure you have the following prerequisites:
-
Node.js and Yarn installed on your system. You can download them from Node.js and Yarn.
-
Nodemon. You can download it from Nodemon(Download it globally)
git clone [email protected]:pokhrelanmol/kilt-didcomm-chatapp.git
client
cd client
yarn install
yarn run dev
backend
cd backend
yarn install
yarn run start
for the backend you are gonna need a mongodb uri. So create .env file inside the backend folder and paste the following text
MONGODB_URL=mongodb+srv://anmolpokhrel:[email protected]/
socket
cd socket
yarn install
yarn run start
Everytime you login into the app the console.log will happen in the socket server.If in any case the server crashes just type rs
to restart server or kill and restart it again using yarn run start
.
There are already an accounts that are registed into the backend if you want you can just use this to login
Open two browser tabs and login with the following account.
Mnemonic: "club luxury collect satoshi awake clinic table tunnel elevator gentle trade easy"
DID: "did:kilt:4qNLDkBxZDaM5U2jKkHro4xkQsyhnXFWMvQJ71WzAfDM51WU"
Mnemonic: "option coconut maximum guitar kiss grass minute six melt youth cross ten"
DID: "did:kilt:4sBCQNWZAL9UkzEzSq56NFPecEzRysjsdAqigY1cPQbuK1W1"
Once the both parties are loggedIn and webRTC peers are connected you can do this step.This happens automatically if you follow the above steps.
- Click on the did uri under tha Chats section(from browser tab 1)
- Click on the did uri under tha Chats section(from browser tab 2)
- Webrtc connection will happen if all things are done properly
- Enjoy realtime secure chatting with the peer.
Our chat application relies on several essential processes, primarily encryption, decryption, and the derivation of shared secrets. Here's an overview:
We use the cryptography library TweetNaCl.js to generate a shared secret using the public and private keys of the two parties involved. This shared secret is derived from the encryption of an empty message using a nonce and keys, which produces a "box" that serves as the shared secret.
import nacl from "tweetnacl";
export function deriveSharedSecret(privateKeyA, publicKeyB, nonce) {
// ...
}
Our application utilizes the shared secret to generate an encryption key using HMAC-SHA256 and a nonce. The message to be encrypted is converted to a JSON string and encrypted using an AES-256-GCM cipher.
import { randomBytes, createHmac, createCipheriv } from "crypto-browserify";
export function deriveKey(sharedSecret) {
// ...
}
export function encryptMessage(message, sharedSecret, signature) {
// ...
}
During decryption, we extract the initialization vector (IV), tag, and encrypted text from the received encrypted message. We then decrypt it using the AES-256-GCM decipher with the derived key and the IV.
import { createDecipheriv } from "crypto-browserify";
import { deriveKey } from "./encryption";
export function decryptMessage(encrypted, sharedSecret) {
// ...
}
Our application uses KILT SDK to sign and verify messages, which greatly enhances security by validating the sender's identity.
We sign messages using the DID's authentication key. The signing function accepts a callback that is used for signing the data, providing flexibility to customize the signing process according to different requirements.
import * as Kilt from "@kiltprotocol/sdk-js";
import { getDidDoc } from "../kilt/didResolver";
export async function signMessage(message, signCallback, didUri) {
// ...
}
To ensure the authenticity of received messages, we use a verification function that checks the message's signature using the sender's public key. If the signature does not match, the function throws an error, indicating possible message tampering or incorrect sender identity.
export async function verifyMessageSignature(message, signature) {
// ...
}
Although our application doesn't fully meet the DIDComm spec, it offers a strong foundation and substantial insight into encryption, decryption, and real-time communication. We'll continue to enhance the app 's decentralization and security, striving to realize the vision of a privacy-preserving, decentralized chat application.