pls forgive, using github editor for expedience, untested changes
pull/517/head
Ryan Tharp 6 years ago committed by GitHub
parent c8cf05558f
commit 968ad9227c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -379,14 +379,14 @@ class LokiPublicChannelAPI {
const privKey = await this.serverAPI.chatAPI.getPrivateKey();
// we might need an annotation that sets the homeserver for media
// better to include this with each attachment...
const ObjToSign = {
const objToSign = {
name: profileName,
version: 1,
annotations: [],
};
const sig = await libsignal.Curve.async.calculateSignature(
privKey,
JSON.stringify(ObjToSign)
JSON.stringify(objToSign)
);
*/
@ -534,6 +534,81 @@ class LokiPublicChannelAPI {
more = res.response.meta.more && res.response.data.length >= params.count;
}
}
async getMessengerData(adnMessage) {
if (!Array.isArray(adnMessage.annotations) || adnMessage.annotations.length === 0) return false;
const noteValue = adnMessage.annotations[0].value;
// signatures now required
if (!noteValue.sig!) {
return false;
}
let timetstamp = 0;
let quote = null;
// timestamp is the only required field we've had since the first deployed version
({ timestamp } = noteValue);
if (noteValue.quote) {
({ quote } = noteValue);
if (quote) {
quote.attachments = [];
}
}
// try to verify signature
let { sig, sigver } = noteValue;
const annoCopy = _.omit(adnMessage.annotations, ['value.sig', 'value.sigver']);
const verifyObj = {
text: adnMessage.text,
version: sigver,
annotations: annoCopy,
};
if (adnMessage.reply_to) {
verifyObj.reply_to = adnMessage.reply_to;
}
const pubKeyBin = StringView.hexToArrayBuffer(
adnMessage.user.username
);
const sigBin = StringView.hexToArrayBuffer(sig);
try {
await libsignal.Curve.async.verifySignature(
pubKeyBin,
JSON.stringify(verifyObj),
sigBin
);
} catch (e) {
if (e.message === 'Invalid signature') {
// keep noise out of the logs, once per start up is enough
if (this.logMop[adnMessage.id] === undefined) {
log.warn(
'Invalid or missing signature on ',
this.serverAPI.baseServerUrl,
this.channelId,
adnMessage.id,
'says',
adnMessage.text,
'from',
adnMessage.user.username,
'signature',
sig,
'signature version',
sigver
);
this.logMop[adnMessage.id] = true;
}
// we now only accept valid messages into the public chat
return false;
}
}
return {
timestamp,
quote
}
}
// get channel messages
async pollForMessages() {
@ -570,103 +645,33 @@ class LokiPublicChannelAPI {
if (!res.err && res.response) {
let receivedAt = new Date().getTime();
res.response.data.reverse().forEach(async adnMessage => {
let timestamp = new Date(adnMessage.created_at).getTime();
// pubKey lives in the username field
const from = adnMessage.user.name;
let sigValid = false;
let sig = false;
let sigvar = false;
let quote = null;
// still update our last received if deleted, not signed or not valid
this.lastGot = !this.lastGot
? adnMessage.id
: Math.max(this.lastGot, adnMessage.id);
if (adnMessage.is_deleted) {
return;
}
if (
Array.isArray(adnMessage.annotations) &&
adnMessage.annotations.length !== 0
) {
const noteValue = adnMessage.annotations[0].value;
({ timestamp } = noteValue);
if (noteValue.quote) {
({ quote } = noteValue);
if (quote) {
quote.attachments = [];
}
}
if (noteValue.sig) {
// try to verify signature
{ sig, sigver } = noteValue;
const annoCopy = { ...adnMessage.annotations };
delete annoCopy[0].value.sig;
delete annoCopy[0].value.sigver;
const verifyObj = {
text: adnMessage.text,
version: sigver,
annotations: annoCopy,
};
if (adnMessage.reply_to) {
verifyObj.reply_to = adnMessage.reply_to;
}
const pubKeyBin = StringView.hexToArrayBuffer(
adnMessage.user.username
);
const sigBin = StringView.hexToArrayBuffer(sig);
try {
await libsignal.Curve.async.verifySignature(
pubKeyBin,
JSON.stringify(verifyObj),
sigBin
);
sigValid = true;
} catch (e) {
if (e.message === 'Invalid signature') {
sigValid = false;
}
}
}
}
// we now only accept valid messages into the public chat
if (sigValid !== true) {
// keep noise out of the logs, once per start up is enough
if (this.logMop[adnMessage.id] === undefined) {
log.warn(
'Invalid or missing signature on ',
this.serverAPI.baseServerUrl,
this.channelId,
adnMessage.id,
'says',
adnMessage.text,
'from',
adnMessage.user.username,
'signature',
sig,
'signature version',
sigver
);
this.logMop[adnMessage.id] = true;
}
return; // Invalid signature
}
if (
!from ||
!timestamp ||
!adnMessage.id ||
!adnMessage.user ||
!adnMessage.user.username ||
!adnMessage.text
!adnMessage.user.username || // pubKey lives in the username field
!adnMessage.user.name || // profileName lives in the name field
!adnMessage.text ||
adnMessage.is_deleted
) {
return; // Invalid message
return; // Invalid or delete message
}
const messengerData = this.getMessengerData(adnMessage);
if (messengerData === false) {
return;
}
const timestamp = messengerData.timestamp;
if (!timestamp) {
return; // Invalid message
}
// Duplicate check
const isDuplicate = message => {
// The username in this case is the users pubKey
@ -694,7 +699,11 @@ class LokiPublicChannelAPI {
timestamp,
},
].splice(-5);
const quote = messengerData.quote;
const from = adnMessage.user.name; // profileName
const messageData = {
serverId: adnMessage.id,
clientVerified: sigValid,
@ -775,17 +784,17 @@ class LokiPublicChannelAPI {
}
}
const privKey = await this.serverAPI.chatAPI.getPrivateKey();
const ObjToSign = {
const objToSign = {
version: 1,
text,
annotations: payload.annotations,
};
if (payload.reply_to) {
ObjToSign.reply_to = payload.reply_to;
objToSign.reply_to = payload.reply_to;
}
const sig = await libsignal.Curve.async.calculateSignature(
privKey,
JSON.stringify(ObjToSign)
JSON.stringify(objToSign)
);
payload.annotations[0].value.sig = StringView.arrayBufferToHex(sig);
payload.annotations[0].value.sigver = 1;

Loading…
Cancel
Save