329 lines
9.4 KiB
JavaScript
329 lines
9.4 KiB
JavaScript
// ./server.js
|
|
|
|
const express = require('express')
|
|
const bodyParser = require('body-parser')
|
|
const cors = require('cors')
|
|
const Chatkit = require('pusher-chatkit-server')
|
|
|
|
var libsignal = require('libsignal');
|
|
|
|
const chatkit = new Chatkit.default({
|
|
instanceLocator: 'v1:us1:366480cc-91f1-4cbd-8c04-68dc96e8ccdf',
|
|
key: '982eaea8-66f5-4bdb-9a2d-14de0fa8b92b:WSgfMJzA8cvZ/fwEqjupJhOpnwQ7qbAEOVze44y+XK0='
|
|
})
|
|
const app = express()
|
|
|
|
app.use(bodyParser.urlencoded({
|
|
extended: false
|
|
}))
|
|
app.use(bodyParser.json())
|
|
app.use(cors())
|
|
//--------
|
|
|
|
var KeyHelper = libsignal.keyhelper;
|
|
var sessionPromise = null;
|
|
|
|
function SignalProtocolStore() {
|
|
this.store = {};
|
|
}
|
|
|
|
SignalProtocolStore.prototype = {
|
|
Direction: {
|
|
SENDING: 1,
|
|
RECEIVING: 2,
|
|
},
|
|
|
|
getIdentityKeyPair: function () {
|
|
return Promise.resolve(this.get('identityKey'));
|
|
},
|
|
//umetnuta nova fun
|
|
getOurIdentity: function () {
|
|
return Promise.resolve(this.get('identityKey'));
|
|
},
|
|
getLocalRegistrationId: function () {
|
|
return Promise.resolve(this.get('registrationId'));
|
|
},
|
|
getOurRegistrationId: function () {
|
|
return Promise.resolve(this.get('identityKey'));
|
|
},
|
|
put: function (key, value) {
|
|
if (key === undefined || value === undefined || key === null || value === null)
|
|
throw new Error("Tried to store undefined/null");
|
|
this.store[key] = value;
|
|
},
|
|
get: function (key, defaultValue) {
|
|
if (key === null || key === undefined)
|
|
throw new Error("Tried to get value for undefined/null key");
|
|
if (key in this.store) {
|
|
return this.store[key];
|
|
} else {
|
|
return defaultValue;
|
|
}
|
|
},
|
|
remove: function (key) {
|
|
if (key === null || key === undefined)
|
|
throw new Error("Tried to remove value for undefined/null key");
|
|
delete this.store[key];
|
|
},
|
|
|
|
isTrustedIdentity: function (identifier, identityKey, direction) {
|
|
if (identifier === null || identifier === undefined) {
|
|
throw new Error("tried to check identity key for undefined/null key");
|
|
}
|
|
if (!(identityKey instanceof ArrayBuffer)) {
|
|
identityKey = identityKey.pubKey;
|
|
//throw new Error("Expected identityKey to be an ArrayBuffer");
|
|
}
|
|
var trusted = this.get('identityKey' + identifier);
|
|
if (trusted === undefined) {
|
|
return Promise.resolve(true);
|
|
}
|
|
return Promise.resolve(util.toString(identityKey) === util.toString(trusted));
|
|
},
|
|
loadIdentityKey: function (identifier) {
|
|
if (identifier === null || identifier === undefined)
|
|
throw new Error("Tried to get identity key for undefined/null key");
|
|
return Promise.resolve(this.get('identityKey' + identifier));
|
|
},
|
|
saveIdentity: function (identifier, identityKey) {
|
|
if (identifier === null || identifier === undefined)
|
|
throw new Error("Tried to put identity key for undefined/null key");
|
|
|
|
var address = new libsignal.SignalProtocolAddress.fromString(identifier);
|
|
|
|
var existing = this.get('identityKey' + address.getName());
|
|
this.put('identityKey' + address.getName(), identityKey)
|
|
|
|
if (existing && util.toString(identityKey) !== util.toString(existing)) {
|
|
return Promise.resolve(true);
|
|
} else {
|
|
return Promise.resolve(false);
|
|
}
|
|
|
|
},
|
|
|
|
/* Returns a prekeypair object or undefined */
|
|
loadPreKey: function (keyId) {
|
|
var res = this.get('25519KeypreKey' + keyId);
|
|
if (res !== undefined) {
|
|
res = {
|
|
pubKey: res.pubKey,
|
|
privKey: res.privKey
|
|
};
|
|
}
|
|
return Promise.resolve(res);
|
|
},
|
|
storePreKey: function (keyId, keyPair) {
|
|
return Promise.resolve(this.put('25519KeypreKey' + keyId, keyPair));
|
|
},
|
|
removePreKey: function (keyId) {
|
|
return Promise.resolve(this.remove('25519KeypreKey' + keyId));
|
|
},
|
|
|
|
/* Returns aa signed keypair object or undefined */
|
|
loadSignedPreKey: function (keyId) {
|
|
var res = this.get('25519KeysignedKey' + keyId);
|
|
if (res !== undefined) {
|
|
res = {
|
|
pubKey: res.pubKey,
|
|
privKey: res.privKey
|
|
};
|
|
}
|
|
return Promise.resolve(res);
|
|
},
|
|
storeSignedPreKey: function (keyId, keyPair) {
|
|
return Promise.resolve(this.put('25519KeysignedKey' + keyId, keyPair));
|
|
},
|
|
removeSignedPreKey: function (keyId) {
|
|
return Promise.resolve(this.remove('25519KeysignedKey' + keyId));
|
|
},
|
|
|
|
loadSession: function (identifier) {
|
|
return Promise.resolve(this.get('session' + identifier));
|
|
},
|
|
storeSession: function (identifier, record) {
|
|
return Promise.resolve(this.put('session' + identifier, record));
|
|
},
|
|
removeSession: function (identifier) {
|
|
return Promise.resolve(this.remove('session' + identifier));
|
|
},
|
|
removeAllSessions: function (identifier) {
|
|
for (var id in this.store) {
|
|
if (id.startsWith('session' + identifier)) {
|
|
delete this.store[id];
|
|
}
|
|
}
|
|
return Promise.resolve();
|
|
}
|
|
};
|
|
|
|
|
|
var senderStore = new SignalProtocolStore();
|
|
|
|
var receiverStore = new SignalProtocolStore();
|
|
//---------------
|
|
function generateIdentity(store) {
|
|
return Promise.all([
|
|
KeyHelper.generateIdentityKeyPair(),
|
|
KeyHelper.generateRegistrationId(),
|
|
]).then(function (result) {
|
|
store.put('identityKey', result[0]);
|
|
store.put('registrationId', result[1]);
|
|
});
|
|
}
|
|
|
|
function generatePreKeyBundle(store, preKeyId, signedPreKeyId) {
|
|
return Promise.all([
|
|
store.getIdentityKeyPair(),
|
|
store.getLocalRegistrationId()
|
|
]).then(function (result) {
|
|
var identity = result[0];
|
|
var registrationId = result[1];
|
|
|
|
return Promise.all([
|
|
KeyHelper.generatePreKey(preKeyId),
|
|
KeyHelper.generateSignedPreKey(identity, signedPreKeyId),
|
|
]).then(function (keys) {
|
|
var preKey = keys[0]
|
|
var signedPreKey = keys[1];
|
|
|
|
store.storePreKey(preKeyId, preKey.keyPair);
|
|
store.storeSignedPreKey(signedPreKeyId, signedPreKey.keyPair);
|
|
|
|
return {
|
|
identityKey: identity.pubKey,
|
|
registrationId: registrationId,
|
|
preKey: {
|
|
keyId: preKeyId,
|
|
publicKey: preKey.keyPair.pubKey
|
|
},
|
|
signedPreKey: {
|
|
keyId: signedPreKeyId,
|
|
publicKey: signedPreKey.keyPair.pubKey,
|
|
signature: signedPreKey.signature
|
|
}
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
|
|
//---------
|
|
|
|
app.post("/cryptMessage", async (req, res) => {
|
|
|
|
//sessionPromise=req.body.data.sessionPromise;
|
|
message = req.body.data.message;
|
|
//senderStore = req.body.data.senderStore;
|
|
//RECEIVER_ADDRESS = new libsignal.ProtocolAddress(req.body.data.receiverAdress.id, req.body.data.receiverAdress.deviceId);
|
|
//----------------
|
|
|
|
|
|
var senderAdress = req.body.data.senderAdress; //"xxxxxxxxx"
|
|
var receiverAdress = req.body.data.receiverAdress; //""yyyyyyyyyyyyy""
|
|
var receiverPreKeyId = req.body.data.receiverPreKeyId; // 1337;
|
|
var receiverSignedKeyId = req.body.data.receiverSignedKeyId; // 1;
|
|
|
|
var SENDER_ADDRESS = new libsignal.ProtocolAddress(senderAdress, 1);
|
|
var RECEIVER_ADDRESS = new libsignal.ProtocolAddress(receiverAdress, 1);
|
|
|
|
var receiverSignedKeyId = 1;
|
|
|
|
var Curve = libsignal.Curve;
|
|
|
|
await Promise.all([
|
|
generateIdentity(senderStore),
|
|
generateIdentity(receiverStore),
|
|
]).then(function () {
|
|
return generatePreKeyBundle(receiverStore, receiverPreKeyId, receiverSignedKeyId);
|
|
}).then(function (preKeyBundle) {
|
|
var builder = new libsignal.SessionBuilder(senderStore, RECEIVER_ADDRESS);
|
|
sessionPromise = builder.initOutgoing(preKeyBundle);
|
|
sessionPromise.then(function () {
|
|
|
|
var originalMessage = Buffer.from(message, 'utf8');
|
|
var senderSessionCipher = new libsignal.SessionCipher(senderStore, RECEIVER_ADDRESS);
|
|
|
|
//var receiverSessionCipher = new libsignal.SessionCipher(receiverStore, SENDER_ADDRESS);
|
|
|
|
senderSessionCipher.encrypt(originalMessage).then(function (ciphertext) {
|
|
console.log("KRI, RECSTORE:", receiverStore);
|
|
console.log("KRI, RECadress:", SENDER_ADDRESS);
|
|
|
|
res.json({
|
|
data: {
|
|
receiverStore: receiverStore,
|
|
SENDER_ADDRESS: SENDER_ADDRESS,
|
|
message: ciphertext.body
|
|
}
|
|
})
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
app.post('/deCryptMessage', (req, res) => {
|
|
|
|
|
|
|
|
message = req.body.data.message;
|
|
const buf5 = Buffer.from(message.split(','));
|
|
//receiverStore = req.body.data.receiverStore;
|
|
//SENDER_ADDRESS = req.body.data.SENDER_ADDRESS;
|
|
senderAdress = req.body.data.senderAdress;
|
|
var SENDER_ADDRESS = new libsignal.ProtocolAddress(senderAdress, 1);
|
|
console.log("DEKRI, RECSTORE:", receiverStore.store.identityKey.pubKey);
|
|
console.log("DEKRI, RECSTORE:", SENDER_ADDRESS);
|
|
//var receiverSessionCipher = new libsignal.SessionCipher(receiverStore, SENDER_ADDRESS);
|
|
|
|
//odavde
|
|
|
|
var receiverSessionCipher = new libsignal.SessionCipher(receiverStore, SENDER_ADDRESS); //ubaceno
|
|
receiverSessionCipher.decryptPreKeyWhisperMessage(buf5, 'binary').then(function (ciphertext) {
|
|
poruka = ciphertext.toString();
|
|
console.log(poruka)
|
|
res.json({
|
|
data: {
|
|
message: poruka
|
|
}
|
|
})
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
app.post('/users', (req, res) => {
|
|
const {
|
|
username
|
|
} = req.body
|
|
const user = {
|
|
name: username,
|
|
id: username
|
|
}
|
|
chatkit
|
|
.createUser(user)
|
|
.then(() => {
|
|
console.log('Created user ', user.name)
|
|
res.status(201).json(user)
|
|
})
|
|
.catch(error => {
|
|
if (error.error === 'services/chatkit/user_already_exists') {
|
|
console.log('User already exists ', user.name)
|
|
res.status(201).json(user)
|
|
} else {
|
|
console.error(error)
|
|
res.status(error.status).json(error)
|
|
}
|
|
})
|
|
})
|
|
|
|
app.listen(3001)
|
|
console.log('Running on port 3001') |