add ConfigurationMessage

pull/1493/head
Audric Ackermann 4 years ago
parent 5c1cd7467b
commit 64737a89d7
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -33,9 +33,17 @@ message TypingMessage {
message Content {
optional DataMessage dataMessage = 1;
optional ReceiptMessage receiptMessage = 5;
optional TypingMessage typingMessage = 6;
optional DataMessage dataMessage = 1;
optional ReceiptMessage receiptMessage = 5;
optional TypingMessage typingMessage = 6;
optional ConfigurationMessage configurationMessage = 7;
}
message KeyPair {
// @required
required bytes publicKey = 1;
// @required
required bytes privateKey = 2;
}
@ -144,6 +152,7 @@ message DataMessage {
optional string profilePicture = 2;
}
message ClosedGroupControlMessage {
enum Type {
@ -156,12 +165,7 @@ message DataMessage {
MEMBER_LEFT = 7;
}
message KeyPair {
// @required
required bytes publicKey = 1;
// @required
required bytes privateKey = 2;
}
message KeyPairWrapper {
// @required
@ -186,20 +190,34 @@ message DataMessage {
optional string serverName = 3;
}
optional string body = 1;
repeated AttachmentPointer attachments = 2;
optional GroupContext group = 3;
optional uint32 flags = 4;
optional uint32 expireTimer = 5;
optional bytes profileKey = 6;
optional uint64 timestamp = 7;
optional Quote quote = 8;
repeated Contact contact = 9;
repeated Preview preview = 10;
optional LokiProfile profile = 101;
optional GroupInvitation groupInvitation = 102;
optional string body = 1;
repeated AttachmentPointer attachments = 2;
optional GroupContext group = 3;
optional uint32 flags = 4;
optional uint32 expireTimer = 5;
optional bytes profileKey = 6;
optional uint64 timestamp = 7;
optional Quote quote = 8;
repeated Contact contact = 9;
repeated Preview preview = 10;
optional LokiProfile profile = 101;
optional GroupInvitation groupInvitation = 102;
optional ClosedGroupControlMessage closedGroupControlMessage = 104;
optional string syncTarget = 105;
}
message ConfigurationMessage {
message ClosedGroup {
optional bytes publicKey = 1;
optional string name = 2;
optional KeyPair encryptionKeyPair = 3;
repeated bytes members = 4;
repeated bytes admins = 5;
}
repeated ClosedGroup closedGroups = 1;
repeated string openGroups = 2;
}
message ReceiptMessage {

@ -385,11 +385,9 @@ async function handleClosedGroupEncryptionKeyPair(
}
// Parse it
let proto: SignalService.DataMessage.ClosedGroupControlMessage.KeyPair;
let proto: SignalService.KeyPair;
try {
proto = SignalService.DataMessage.ClosedGroupControlMessage.KeyPair.decode(
plaintext
);
proto = SignalService.KeyPair.decode(plaintext);
if (
!proto ||
proto.privateKey.length === 0 ||

@ -673,15 +673,11 @@ export async function generateAndSendNewEncryptionKeyPair(
);
return;
}
const proto = new SignalService.DataMessage.ClosedGroupControlMessage.KeyPair(
{
privateKey: newKeyPair?.privateKeyData,
publicKey: newKeyPair?.publicKeyData,
}
);
const plaintext = SignalService.DataMessage.ClosedGroupControlMessage.KeyPair.encode(
proto
).finish();
const proto = new SignalService.KeyPair({
privateKey: newKeyPair?.privateKeyData,
publicKey: newKeyPair?.publicKeyData,
});
const plaintext = SignalService.KeyPair.encode(proto).finish();
// Distribute it
const wrappers = await Promise.all(

@ -16,4 +16,8 @@ export abstract class Message {
}
this.identifier = identifier || uuid();
}
public isSelfSendValid() {
return false;
}
}

@ -0,0 +1,90 @@
// this is not a very good name, but a configuration message is a message sent to our other devices so sync our current public and closed groups
import { ContentMessage } from './ContentMessage';
import { SignalService } from '../../../../protobuf';
import { MessageParams } from '../Message';
import { Constants } from '../../..';
import { ECKeyPair } from '../../../../receiver/keypairs';
import { fromHexToArray } from '../../../utils/String';
interface ConfigurationMessageParams extends MessageParams {
activeClosedGroups: Array<ConfigurationMessageClosedGroup>;
activeOpenGroups: Array<string>;
}
export class ConfigurationMessage extends ContentMessage {
private readonly activeClosedGroups: Array<ConfigurationMessageClosedGroup>;
private readonly activeOpenGroups: Array<string>;
constructor(params: ConfigurationMessageParams) {
super({ timestamp: params.timestamp, identifier: params.identifier });
this.activeClosedGroups = params.activeClosedGroups;
this.activeOpenGroups = params.activeOpenGroups;
}
public ttl(): number {
return Constants.TTL_DEFAULT.TYPING_MESSAGE;
}
public contentProto(): SignalService.Content {
return new SignalService.Content({
configurationMessage: this.configurationProto(),
});
}
protected configurationProto(): SignalService.ConfigurationMessage {
return new SignalService.ConfigurationMessage({
closedGroups: this.mapClosedGroupsObjectToProto(this.activeClosedGroups),
openGroups: this.activeOpenGroups,
});
}
private mapClosedGroupsObjectToProto(
closedGroups: Array<ConfigurationMessageClosedGroup>
): Array<SignalService.ConfigurationMessage.ClosedGroup> {
return (closedGroups || []).map(m =>
new ConfigurationMessageClosedGroup(m).toProto()
);
}
}
export class ConfigurationMessageClosedGroup {
public publicKey: string;
public name: string;
public encryptionKeyPair: ECKeyPair;
public members: Array<string>;
public admins: Array<string>;
public constructor({
publicKey,
name,
encryptionKeyPair,
members,
admins,
}: {
publicKey: string;
name: string;
encryptionKeyPair: ECKeyPair;
members: Array<string>;
admins: Array<string>;
}) {
this.publicKey = publicKey;
this.name = name;
this.encryptionKeyPair = encryptionKeyPair;
this.members = members;
this.admins = admins;
}
public toProto(): SignalService.ConfigurationMessage.ClosedGroup {
return new SignalService.ConfigurationMessage.ClosedGroup({
publicKey: fromHexToArray(this.publicKey),
name: this.name,
encryptionKeyPair: {
publicKey: this.encryptionKeyPair.publicKeyData,
privateKey: this.encryptionKeyPair.privateKeyData,
},
members: this.members.map(fromHexToArray),
admins: this.admins.map(fromHexToArray),
});
}
}

@ -73,7 +73,7 @@ export class ClosedGroupNewMessage extends ClosedGroupMessage {
fromHexToArray
);
try {
dataMessage.closedGroupControlMessage.encryptionKeyPair = new SignalService.DataMessage.ClosedGroupControlMessage.KeyPair();
dataMessage.closedGroupControlMessage.encryptionKeyPair = new SignalService.KeyPair();
dataMessage.closedGroupControlMessage.encryptionKeyPair.privateKey = new Uint8Array(
this.keypair.privateKeyData
);
@ -87,4 +87,8 @@ export class ClosedGroupNewMessage extends ClosedGroupMessage {
return dataMessage;
}
public isSelfSendValid() {
return true;
}
}

@ -2,11 +2,20 @@ import { RawMessage } from '../types/RawMessage';
import {
ContentMessage,
ExpirationTimerUpdateMessage,
TypingMessage,
} from '../messages/outgoing';
import { EncryptionType, PubKey } from '../types';
import { ClosedGroupMessage } from '../messages/outgoing/content/data/group/ClosedGroupMessage';
import { ClosedGroupNewMessage } from '../messages/outgoing/content/data/group/ClosedGroupNewMessage';
import { ConversationModel } from '../../../js/models/conversations';
import {
ConfigurationMessage,
ConfigurationMessageClosedGroup,
} from '../messages/outgoing/content/ConfigurationMessage';
import uuid from 'uuid';
import * as Data from '../../../js/modules/data';
import { UserUtils } from '.';
import { ECKeyPair } from '../../receiver/keypairs';
import _ from 'lodash';
export function getEncryptionTypeFromMessageType(
message: ContentMessage
@ -51,3 +60,55 @@ export async function toRawMessage(
return rawMessage;
}
export const getCurrentConfigurationMessage = async (
convos: Array<ConversationModel>
) => {
const ourPubKey = (await UserUtils.getOurNumber()).key;
const openGroupsIds = convos
.filter(
c =>
!!c.get('active_at') &&
c.get('members').includes(ourPubKey) &&
c.isPublic() &&
!c.get('left')
)
.map(c => c.id) as Array<string>;
const closedGroupModels = convos.filter(
c =>
!!c.get('active_at') &&
c.isMediumGroup() &&
!c.get('left') &&
!c.get('isKickedFromGroup')
);
const closedGroups = await Promise.all(
closedGroupModels.map(async c => {
const groupPubKey = c.get('id');
const fetchEncryptionKeyPair = await Data.getLatestClosedGroupEncryptionKeyPair(
groupPubKey
);
if (!fetchEncryptionKeyPair) {
return null;
}
return new ConfigurationMessageClosedGroup({
publicKey: groupPubKey,
name: c.get('name'),
members: c.get('members') || [],
admins: c.get('groupAdmins') || [],
encryptionKeyPair: ECKeyPair.fromHexKeyPair(fetchEncryptionKeyPair),
});
})
);
const onlyValidClosedGroup = closedGroups.filter(m => m !== null) as Array<
ConfigurationMessageClosedGroup
>;
return new ConfigurationMessage({
identifier: uuid(),
timestamp: Date.now(),
activeOpenGroups: openGroupsIds,
activeClosedGroups: onlyValidClosedGroup,
});
};

Loading…
Cancel
Save