feat: in theory add in the subkey auth callbacks and make a default bytearray signer callback

This commit is contained in:
0x330a 2023-10-24 17:15:28 +11:00
parent 4f78f998fe
commit d63b5f85df
20 changed files with 218 additions and 381 deletions

View File

@ -7,6 +7,7 @@ import org.session.libsession.messaging.jobs.AttachmentDownloadJob
import org.session.libsession.messaging.jobs.AttachmentUploadJob
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
import org.session.libsession.messaging.jobs.GroupAvatarDownloadJob
import org.session.libsession.messaging.jobs.InviteContactJob
import org.session.libsession.messaging.jobs.Job
import org.session.libsession.messaging.jobs.MessageReceiveJob
import org.session.libsession.messaging.jobs.MessageSendJob
@ -73,6 +74,13 @@ class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
return result.firstOrNull { job -> job.attachmentID == attachmentID }
}
fun getGroupInviteJob(groupSessionId: String, memberSessionId: String): InviteContactJob? {
val database = databaseHelper.readableDatabase
return database.getAll(sessionJobTable, "$jobType = ?", arrayOf(InviteContactJob.KEY)) { cursor ->
jobFromCursor(cursor) as? InviteContactJob
}.firstOrNull { it != null && it.groupSessionId == groupSessionId && it.memberSessionId == memberSessionId }
}
fun getMessageSendJob(messageSendJobID: String): MessageSendJob? {
val database = databaseHelper.readableDatabase
return database.get(sessionJobTable, "$jobID = ? AND $jobType = ?", arrayOf( messageSendJobID, MessageSendJob.KEY )) { cursor ->

View File

@ -919,7 +919,7 @@ open class Storage(
DatabaseComponent.get(context).groupDatabase().create(groupId, title, members, avatar, relay, admins, formationTimestamp)
}
override fun createNewGroup(groupName: String, groupDescription: String, members: Set<SessionId>): Optional<Recipient> {
override fun createNewGroup(groupName: String, groupDescription: String, members: Set<Contact>): Optional<Recipient> {
val userGroups = configFactory.userGroups ?: return Optional.absent()
val convoVolatile = configFactory.convoVolatile ?: return Optional.absent()
val ourSessionId = getUserPublicKey() ?: return Optional.absent()
@ -938,10 +938,10 @@ open class Storage(
}
groupMembers.set(
LibSessionGroupMember(ourSessionId, "admin", admin = true)
LibSessionGroupMember(ourSessionId, getUserProfile().displayName, admin = true)
)
members.forEach { groupMembers.set(LibSessionGroupMember(it.hexString(), "member", invitePending = true)) }
members.forEach { groupMembers.set(LibSessionGroupMember(it.sessionID, it.name, invitePending = true)) }
val groupKeys = configFactory.constructGroupKeysConfig(group.groupSessionId,
info = groupInfo,

View File

@ -206,7 +206,7 @@ class ConfigFactory(
) ?: byteArrayOf()
// Put it all together
GroupKeysConfig.newInstance(
val keys = GroupKeysConfig.newInstance(
userSk,
Hex.fromStringCondensed(groupSessionId.publicKey),
sk,
@ -214,6 +214,9 @@ class ConfigFactory(
info,
members
)
info.free()
members.free()
keys
}
override fun getGroupMemberConfig(groupSessionId: SessionId): GroupMembersConfig? = getGroupAuthInfo(groupSessionId)?.let { (sk, auth) ->

View File

@ -49,9 +49,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import network.loki.messenger.R
import network.loki.messenger.databinding.FragmentCreateGroupBinding
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.Device
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.utilities.SessionId
import org.thoughtcrime.securesms.conversation.start.NewConversationDelegate
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.ui.AppTheme
@ -136,7 +136,7 @@ class CreateGroupFragment : Fragment() {
data class CreateGroupState (
val groupName: String,
val groupDescription: String,
val members: Set<SessionId>
val members: Set<Contact>
)
@Composable
@ -237,7 +237,7 @@ fun CreateGroup(
@Composable
fun MemberList(contacts: Collection<SessionId>, modifier: Modifier = Modifier) {
fun MemberList(contacts: Collection<Contact>, modifier: Modifier = Modifier) {
Column(modifier = modifier
.fillMaxWidth()
.defaultMinSize(minHeight = 240.dp)) {

View File

@ -45,7 +45,7 @@ class CreateGroupViewModel @Inject constructor(
val name = createGroupState.groupName
val description = createGroupState.groupDescription
val members = createGroupState.members
val members = createGroupState.members.toMutableSet()
// do some validation
// need a name
@ -55,7 +55,11 @@ class CreateGroupViewModel @Inject constructor(
)
return null
}
// TODO: need at least two members
storage.getAllContacts().forEach { contact ->
members.add(contact)
}
if (members.size <= 1) {
_viewState.postValue(
CreateGroupFragment.ViewState(false, R.string.activity_create_closed_group_not_enough_group_members_error)

View File

@ -243,4 +243,18 @@ Java_network_loki_messenger_libsession_1util_GroupKeysConfig_makeSubAccount(JNIE
auto new_subaccount_key = ptr->swarm_make_subaccount(deserialized_id.data(), can_write, can_delete);
auto jbytes = util::bytes_from_ustring(env, new_subaccount_key);
return jbytes;
}
extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_subAccountSign(JNIEnv *env,
jobject thiz,
jbyteArray message,
jbyteArray signing_value) {
std::lock_guard lock{util::util_mutex_};
auto ptr = ptrToKeys(env, thiz);
auto message_ustring = util::ustring_from_bytes(env, message);
auto signing_value_ustring = util::ustring_from_bytes(env, signing_value);
auto swarm_auth = ptr->swarm_subaccount_sign(message_ustring, signing_value_ustring, false);
return util::deserialize_swarm_auth(env, swarm_auth);
}

View File

@ -197,6 +197,16 @@ namespace util {
return our_stack;
}
jobject deserialize_swarm_auth(JNIEnv *env, session::config::groups::Keys::swarm_auth auth) {
jclass swarm_auth_class = env->FindClass("network/loki/messenger/libsession_util/GroupKeysConfig$SwarmAuth");
jmethodID constructor = env->GetMethodID(swarm_auth_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
jstring sub_account = env->NewStringUTF(auth.subaccount.data());
jstring sub_account_sig = env->NewStringUTF(auth.subaccount_sig.data());
jstring signature = env->NewStringUTF(auth.signature.data());
return env->NewObject(swarm_auth_class, constructor, sub_account, sub_account_sig, signature);
}
jobject jlongFromOptional(JNIEnv* env, std::optional<long long> optional) {
if (!optional) {
return nullptr;

View File

@ -30,6 +30,7 @@ namespace util {
jobject serialize_session_id(JNIEnv* env, std::string_view session_id);
std::string deserialize_session_id(JNIEnv* env, jobject session_id);
jobject build_string_stack(JNIEnv* env, std::vector<std::string> to_add);
jobject deserialize_swarm_auth(JNIEnv *env, session::config::groups::Keys::swarm_auth auth);
}
#endif

View File

@ -334,4 +334,12 @@ class GroupKeysConfig(pointer: Long): ConfigSig(pointer) {
external fun makeSubAccount(sessionId: SessionId, canWrite: Boolean = true, canDelete: Boolean = false): ByteArray
external fun subAccountSign(message: ByteArray, signingValue: ByteArray): SwarmAuth
data class SwarmAuth(
val subAccount: String,
val subAccountSig: String,
val signature: String
)
}

View File

@ -12,6 +12,12 @@ sealed class GroupInfo {
val authData: ByteArray,
val priority: Long,
): GroupInfo() {
companion object {
private const val AUTH_DATA_LENGTH = 100
fun isAuthData(byteArray: ByteArray) = byteArray.size == AUTH_DATA_LENGTH
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

View File

@ -157,7 +157,7 @@ interface StorageProtocol {
fun setExpirationTimer(address: String, duration: Int)
// Closed Groups
fun createNewGroup(groupName: String, groupDescription: String, members: Set<SessionId>): Optional<Recipient>
fun createNewGroup(groupName: String, groupDescription: String, members: Set<Contact>): Optional<Recipient>
fun getMembers(groupPublicKey: String): List<LibSessionGroupMember>
fun acceptClosedGroupInvite(groupId: SessionId, name: String, authData: ByteArray, invitingAdmin: SessionId)
fun setGroupInviteComplete(approved: Boolean, invitee: String, closedGroup: SessionId)

View File

@ -0,0 +1,30 @@
package org.session.libsession.messaging.jobs
import org.session.libsession.messaging.utilities.Data
class InviteContactJob(val groupSessionId: String, val memberSessionId: String): Job {
companion object {
const val KEY = "InviteContactJob"
private const val GROUP = "group"
private const val MEMBER = "member"
}
override var delegate: JobDelegate? = null
override var id: String? = null
override var failureCount: Int = 0
override val maxFailureCount: Int = 1
override suspend fun execute(dispatcherName: String) {
TODO("Not yet implemented")
}
override fun serialize(): Data =
Data.Builder()
.putString(GROUP, groupSessionId)
.putString(MEMBER, memberSessionId)
.build()
override fun getFactoryKey(): String = KEY
}

View File

@ -227,6 +227,7 @@ class JobQueue : JobDelegate {
OpenGroupDeleteJob.KEY,
RetrieveProfileAvatarJob.KEY,
ConfigurationSyncJob.KEY,
InviteContactJob.KEY
)
allJobTypes.forEach { type ->
resumePendingJobs(type)

View File

@ -7,7 +7,10 @@ import org.session.libsignal.protos.SignalServiceProtos.DataMessage.GroupUpdateM
class GroupUpdated(val inner: GroupUpdateMessage): ControlMessage() {
companion object {
fun fromProto(message: GroupUpdateMessage): GroupUpdated = GroupUpdated(message)
fun fromProto(message: Content): GroupUpdated? =
if (message.hasDataMessage() && message.dataMessage.hasGroupUpdateMessage())
GroupUpdated(message.dataMessage.groupUpdateMessage)
else null
}
override fun toProto(): Content {

View File

@ -7,6 +7,7 @@ import org.session.libsession.messaging.messages.control.ClosedGroupControlMessa
import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.messages.control.DataExtractionNotification
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
import org.session.libsession.messaging.messages.control.GroupUpdated
import org.session.libsession.messaging.messages.control.MessageRequestResponse
import org.session.libsession.messaging.messages.control.ReadReceipt
import org.session.libsession.messaging.messages.control.SharedConfigurationMessage
@ -154,7 +155,7 @@ object MessageReceiver {
CallMessage.fromProto(proto) ?:
SharedConfigurationMessage.fromProto(proto) ?:
VisibleMessage.fromProto(proto) ?:
ClosedGroupMessage.fromProto(proto) ?: run {
GroupUpdated.fromProto(proto) ?: run {
throw Error.UnknownMessage
}
val isUserBlindedSender = sender == openGroupPublicKey?.let { SodiumUtilities.blindedKeyPair(it, MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!) }?.let { SessionId(IdPrefix.BLINDED, it.publicKey.asBytes).hexString() }

View File

@ -1,5 +1,6 @@
package org.session.libsession.messaging.sending_receiving
import network.loki.messenger.libsession_util.util.GroupInfo.ClosedGroupInfo.Companion.isAuthData
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.deferred
import org.session.libsession.messaging.MessagingModuleConfiguration
@ -26,6 +27,8 @@ import org.session.libsession.messaging.utilities.MessageWrapper
import org.session.libsession.messaging.utilities.SodiumUtilities
import org.session.libsession.snode.RawResponsePromise
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.snode.SnodeAPI.signingKeyCallback
import org.session.libsession.snode.SnodeAPI.subkeyCallback
import org.session.libsession.snode.SnodeMessage
import org.session.libsession.snode.SnodeModule
import org.session.libsession.utilities.Address
@ -225,7 +228,12 @@ object MessageSender {
if (destination is Destination.ClosedGroup) {
// possibly handle a failure for no user groups or no closed group signing key?
val signingKey = configFactory.userGroups!!.getClosedGroup(destination.publicKey)!!.signingKey()
SnodeAPI.sendAuthenticatedMessage(snodeMessage, signingKey, namespace = namespace)
val callback = if (isAuthData(signingKey)) {
val keys = configFactory.getGroupKeysConfig(SessionId.from(destination.publicKey))!!
val params = subkeyCallback(signingKey, keys)
params
} else signingKeyCallback(signingKey)
SnodeAPI.sendAuthenticatedMessage(snodeMessage, callback, namespace = namespace)
} else {
SnodeAPI.sendMessage(snodeMessage, requiresAuth = false, namespace = namespace)
}

View File

@ -281,7 +281,7 @@ class OpenGroupPoller(private val server: String, private val executorService: S
mappingCache[it.recipient] = mapping
}
val threadId = Message.getThreadId(message, null, MessagingModuleConfiguration.shared.storage, false)
MessageReceiver.handle(message, proto, threadId ?: -1, null)
MessageReceiver.handle(message, proto, threadId ?: -1, null, null)
} catch (e: Exception) {
Log.e("Loki", "Couldn't handle direct message", e)
}

View File

@ -11,6 +11,7 @@ import com.goterl.lazysodium.interfaces.PwHash
import com.goterl.lazysodium.interfaces.SecretBox
import com.goterl.lazysodium.interfaces.Sign
import com.goterl.lazysodium.utils.Key
import network.loki.messenger.libsession_util.GroupKeysConfig
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.all
import nl.komponents.kovenant.deferred
@ -692,28 +693,45 @@ object SnodeAPI {
}
}
fun sendAuthenticatedMessage(message: SnodeMessage, signingKey: ByteArray, namespace: Int): RawResponsePromise {
fun signingKeyCallback(signingKey: ByteArray): SignCallback = { message, timestamp, namespace ->
val signature = ByteArray(Sign.BYTES)
try {
val verificationData = message.toByteArray()
sodium.cryptoSignDetached(signature, verificationData, verificationData.size.toLong(), signingKey)
} catch (exception: Exception) {
throw Error.SigningFailed
}
mapOf(
"timestamp" to timestamp,
"signature" to Base64.encodeBytes(signature),
"namespace" to namespace
)
}
fun subkeyCallback(authData: ByteArray, groupKeysConfig: GroupKeysConfig): SignCallback = { message, timestamp, namespace ->
val (subaccount, subaccountSig, sig) = groupKeysConfig.subAccountSign(message.toByteArray(),authData)
val params = mapOf(
"subaccount" to subaccount,
"subaccount_sig" to subaccountSig,
"signature" to sig,
"timestamp" to timestamp,
"namespace" to namespace
)
groupKeysConfig.free()
params
}
fun sendAuthenticatedMessage(message: SnodeMessage, signCallback: SignCallback, namespace: Int): RawResponsePromise {
val pubKey = message.recipient
return retryIfNeeded(maxRetryCount) {
val signature = ByteArray(Sign.BYTES)
// assume namespace here is non-zero, as zero namespace doesn't require auth
val sigTimestamp = nowWithOffset
val verificationData = "store$namespace$sigTimestamp".toByteArray()
try {
sodium.cryptoSignDetached(signature, verificationData, verificationData.size.toLong(), signingKey)
} catch (exception: Exception) {
return@retryIfNeeded Promise.ofFail(Error.SigningFailed)
}
val messageToSign = "store$namespace$sigTimestamp"
val parameters = message.toJSON().toMutableMap<String,Any>()
parameters += mapOf(
"timestamp" to sigTimestamp,
"signature" to Base64.encodeBytes(signature),
"namespace" to namespace
)
parameters += signCallback(messageToSign, sigTimestamp, namespace)
getSingleTargetSnode(pubKey).bind { targetSnode ->
invoke(Snode.Method.SendMessage, targetSnode, parameters, pubKey)
@ -1014,6 +1032,8 @@ object SnodeAPI {
}
}
typealias SignCallback = (String, Long, Int)->Map<String,Any>
// Type Aliases
typealias RawResponse = Map<*, *>
typealias MessageListPromise = Promise<List<Pair<SignalServiceProtos.Envelope, String?>>, Exception>

View File

@ -192,8 +192,6 @@ message DataMessage {
message GroupUpdateInviteResponseMessage {
// @required
required bool isApproved = 1; // Whether the request was approved
optional bytes profileKey = 2;
optional LokiProfile profile = 3;
}
message GroupUpdateDeleteMemberContentMessage {

View File

@ -16731,30 +16731,6 @@ public final class SignalServiceProtos {
* </pre>
*/
boolean getIsApproved();
// optional bytes profileKey = 2;
/**
* <code>optional bytes profileKey = 2;</code>
*/
boolean hasProfileKey();
/**
* <code>optional bytes profileKey = 2;</code>
*/
com.google.protobuf.ByteString getProfileKey();
// optional .signalservice.DataMessage.LokiProfile profile = 3;
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
boolean hasProfile();
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile getProfile();
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfileOrBuilder getProfileOrBuilder();
}
/**
* Protobuf type {@code signalservice.DataMessage.GroupUpdateInviteResponseMessage}
@ -16812,24 +16788,6 @@ public final class SignalServiceProtos {
isApproved_ = input.readBool();
break;
}
case 18: {
bitField0_ |= 0x00000002;
profileKey_ = input.readBytes();
break;
}
case 26: {
org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.Builder subBuilder = null;
if (((bitField0_ & 0x00000004) == 0x00000004)) {
subBuilder = profile_.toBuilder();
}
profile_ = input.readMessage(org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.PARSER, extensionRegistry);
if (subBuilder != null) {
subBuilder.mergeFrom(profile_);
profile_ = subBuilder.buildPartial();
}
bitField0_ |= 0x00000004;
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@ -16894,48 +16852,8 @@ public final class SignalServiceProtos {
return isApproved_;
}
// optional bytes profileKey = 2;
public static final int PROFILEKEY_FIELD_NUMBER = 2;
private com.google.protobuf.ByteString profileKey_;
/**
* <code>optional bytes profileKey = 2;</code>
*/
public boolean hasProfileKey() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>optional bytes profileKey = 2;</code>
*/
public com.google.protobuf.ByteString getProfileKey() {
return profileKey_;
}
// optional .signalservice.DataMessage.LokiProfile profile = 3;
public static final int PROFILE_FIELD_NUMBER = 3;
private org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile profile_;
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public boolean hasProfile() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile getProfile() {
return profile_;
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfileOrBuilder getProfileOrBuilder() {
return profile_;
}
private void initFields() {
isApproved_ = false;
profileKey_ = com.google.protobuf.ByteString.EMPTY;
profile_ = org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.getDefaultInstance();
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@ -16956,12 +16874,6 @@ public final class SignalServiceProtos {
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeBool(1, isApproved_);
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBytes(2, profileKey_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeMessage(3, profile_);
}
getUnknownFields().writeTo(output);
}
@ -16975,14 +16887,6 @@ public final class SignalServiceProtos {
size += com.google.protobuf.CodedOutputStream
.computeBoolSize(1, isApproved_);
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(2, profileKey_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(3, profile_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@ -17091,7 +16995,6 @@ public final class SignalServiceProtos {
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
getProfileFieldBuilder();
}
}
private static Builder create() {
@ -17102,14 +17005,6 @@ public final class SignalServiceProtos {
super.clear();
isApproved_ = false;
bitField0_ = (bitField0_ & ~0x00000001);
profileKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000002);
if (profileBuilder_ == null) {
profile_ = org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.getDefaultInstance();
} else {
profileBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000004);
return this;
}
@ -17142,18 +17037,6 @@ public final class SignalServiceProtos {
to_bitField0_ |= 0x00000001;
}
result.isApproved_ = isApproved_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002;
}
result.profileKey_ = profileKey_;
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004;
}
if (profileBuilder_ == null) {
result.profile_ = profile_;
} else {
result.profile_ = profileBuilder_.build();
}
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@ -17173,12 +17056,6 @@ public final class SignalServiceProtos {
if (other.hasIsApproved()) {
setIsApproved(other.getIsApproved());
}
if (other.hasProfileKey()) {
setProfileKey(other.getProfileKey());
}
if (other.hasProfile()) {
mergeProfile(other.getProfile());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@ -17259,159 +17136,6 @@ public final class SignalServiceProtos {
return this;
}
// optional bytes profileKey = 2;
private com.google.protobuf.ByteString profileKey_ = com.google.protobuf.ByteString.EMPTY;
/**
* <code>optional bytes profileKey = 2;</code>
*/
public boolean hasProfileKey() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>optional bytes profileKey = 2;</code>
*/
public com.google.protobuf.ByteString getProfileKey() {
return profileKey_;
}
/**
* <code>optional bytes profileKey = 2;</code>
*/
public Builder setProfileKey(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000002;
profileKey_ = value;
onChanged();
return this;
}
/**
* <code>optional bytes profileKey = 2;</code>
*/
public Builder clearProfileKey() {
bitField0_ = (bitField0_ & ~0x00000002);
profileKey_ = getDefaultInstance().getProfileKey();
onChanged();
return this;
}
// optional .signalservice.DataMessage.LokiProfile profile = 3;
private org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile profile_ = org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.getDefaultInstance();
private com.google.protobuf.SingleFieldBuilder<
org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile, org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.Builder, org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfileOrBuilder> profileBuilder_;
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public boolean hasProfile() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile getProfile() {
if (profileBuilder_ == null) {
return profile_;
} else {
return profileBuilder_.getMessage();
}
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public Builder setProfile(org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile value) {
if (profileBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
}
profile_ = value;
onChanged();
} else {
profileBuilder_.setMessage(value);
}
bitField0_ |= 0x00000004;
return this;
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public Builder setProfile(
org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.Builder builderForValue) {
if (profileBuilder_ == null) {
profile_ = builderForValue.build();
onChanged();
} else {
profileBuilder_.setMessage(builderForValue.build());
}
bitField0_ |= 0x00000004;
return this;
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public Builder mergeProfile(org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile value) {
if (profileBuilder_ == null) {
if (((bitField0_ & 0x00000004) == 0x00000004) &&
profile_ != org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.getDefaultInstance()) {
profile_ =
org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.newBuilder(profile_).mergeFrom(value).buildPartial();
} else {
profile_ = value;
}
onChanged();
} else {
profileBuilder_.mergeFrom(value);
}
bitField0_ |= 0x00000004;
return this;
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public Builder clearProfile() {
if (profileBuilder_ == null) {
profile_ = org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.getDefaultInstance();
onChanged();
} else {
profileBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000004);
return this;
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.Builder getProfileBuilder() {
bitField0_ |= 0x00000004;
onChanged();
return getProfileFieldBuilder().getBuilder();
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
public org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfileOrBuilder getProfileOrBuilder() {
if (profileBuilder_ != null) {
return profileBuilder_.getMessageOrBuilder();
} else {
return profile_;
}
}
/**
* <code>optional .signalservice.DataMessage.LokiProfile profile = 3;</code>
*/
private com.google.protobuf.SingleFieldBuilder<
org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile, org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.Builder, org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfileOrBuilder>
getProfileFieldBuilder() {
if (profileBuilder_ == null) {
profileBuilder_ = new com.google.protobuf.SingleFieldBuilder<
org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile, org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfile.Builder, org.session.libsignal.protos.SignalServiceProtos.DataMessage.LokiProfileOrBuilder>(
profile_,
getParentForChildren(),
isClean());
profile_ = null;
}
return profileBuilder_;
}
// @@protoc_insertion_point(builder_scope:signalservice.DataMessage.GroupUpdateInviteResponseMessage)
}
@ -35777,7 +35501,7 @@ public final class SignalServiceProtos {
"actionNotification\022<\n\004type\030\001 \002(\0162..signa" +
"lservice.DataExtractionNotification.Type" +
"\022\021\n\ttimestamp\030\002 \001(\004\"\'\n\004Type\022\016\n\nSCREENSHO" +
"T\020\001\022\017\n\013MEDIA_SAVED\020\002\"\304\034\n\013DataMessage\022\014\n\004",
"T\020\001\022\017\n\013MEDIA_SAVED\020\002\"\366\033\n\013DataMessage\022\014\n\004",
"body\030\001 \001(\t\0225\n\013attachments\030\002 \003(\0132 .signal" +
"service.AttachmentPointer\022\r\n\005flags\030\004 \001(\r" +
"\022\023\n\013expireTimer\030\005 \001(\r\022\022\n\nprofileKey\030\006 \001(" +
@ -35842,79 +35566,77 @@ public final class SignalServiceProtos {
"oupUpdateMemberChangeMessage.Type\022\030\n\020mem" +
"berPublicKeys\030\002 \003(\014\",\n\004Type\022\t\n\005ADDED\020\001\022\013" +
"\n\007REMOVED\020\002\022\014\n\010PROMOTED\020\003\032\036\n\034GroupUpdate" +
"MemberLeftMessage\032\203\001\n GroupUpdateInviteR" +
"esponseMessage\022\022\n\nisApproved\030\001 \002(\010\022\022\n\npr" +
"ofileKey\030\002 \001(\014\0227\n\007profile\030\003 \001(\0132&.signal" +
"service.DataMessage.LokiProfile\032Y\n%Group" +
"UpdateDeleteMemberContentMessage\022\030\n\020memb" +
"erPublicKeys\030\001 \003(\014\022\026\n\016adminSignature\030\002 \002",
"(\014\032\203\005\n\031ClosedGroupControlMessage\022G\n\004type" +
"\030\001 \002(\01629.signalservice.DataMessage.Close" +
"dGroupControlMessage.Type\022\021\n\tpublicKey\030\002" +
" \001(\014\022\014\n\004name\030\003 \001(\t\0221\n\021encryptionKeyPair\030" +
"\004 \001(\0132\026.signalservice.KeyPair\022\017\n\007members" +
"\030\005 \003(\014\022\016\n\006admins\030\006 \003(\014\022U\n\010wrappers\030\007 \003(\013" +
"2C.signalservice.DataMessage.ClosedGroup" +
"ControlMessage.KeyPairWrapper\022\027\n\017expirat" +
"ionTimer\030\010 \001(\r\022\030\n\020memberPrivateKey\030\t \001(\014" +
"\022\022\n\nprivateKey\030\n \001(\014\032=\n\016KeyPairWrapper\022\021",
"\n\tpublicKey\030\001 \002(\014\022\030\n\020encryptedKeyPair\030\002 " +
"\002(\014\"\312\001\n\004Type\022\007\n\003NEW\020\001\022\027\n\023ENCRYPTION_KEY_" +
"PAIR\020\003\022\017\n\013NAME_CHANGE\020\004\022\021\n\rMEMBERS_ADDED" +
"\020\005\022\023\n\017MEMBERS_REMOVED\020\006\022\017\n\013MEMBER_LEFT\020\007" +
"\022\n\n\006INVITE\020\t\022\013\n\007PROMOTE\020\n\022\020\n\014DELETE_GROU" +
"P\020\013\022\023\n\017DELETE_MESSAGES\020\014\022\026\n\022DELETE_ATTAC" +
"HMENTS\020\r\032\222\001\n\010Reaction\022\n\n\002id\030\001 \002(\004\022\016\n\006aut" +
"hor\030\002 \002(\t\022\r\n\005emoji\030\003 \001(\t\022:\n\006action\030\004 \002(\016" +
"2*.signalservice.DataMessage.Reaction.Ac" +
"tion\"\037\n\006Action\022\t\n\005REACT\020\000\022\n\n\006REMOVE\020\001\"$\n",
"\005Flags\022\033\n\027EXPIRATION_TIMER_UPDATE\020\002\"B\n\022G" +
"roupDeleteMessage\022\021\n\tpublicKey\030\001 \002(\014\022\031\n\021" +
"lastEncryptionKey\030\002 \002(\014\"\030\n\026GroupMemberLe" +
"ftMessage\"O\n\022GroupInviteMessage\022\021\n\tpubli" +
"cKey\030\001 \002(\014\022\014\n\004name\030\002 \002(\t\022\030\n\020memberPrivat" +
"eKey\030\003 \002(\014\"E\n\023GroupPromoteMessage\022\021\n\tpub" +
"licKey\030\001 \002(\014\022\033\n\023encryptedPrivateKey\030\002 \002(" +
"\014\"\352\001\n\013CallMessage\022-\n\004type\030\001 \002(\0162\037.signal" +
"service.CallMessage.Type\022\014\n\004sdps\030\002 \003(\t\022\027" +
"\n\017sdpMLineIndexes\030\003 \003(\r\022\017\n\007sdpMids\030\004 \003(\t",
"\022\014\n\004uuid\030\005 \002(\t\"f\n\004Type\022\r\n\tPRE_OFFER\020\006\022\t\n" +
"\005OFFER\020\001\022\n\n\006ANSWER\020\002\022\026\n\022PROVISIONAL_ANSW" +
"ER\020\003\022\022\n\016ICE_CANDIDATES\020\004\022\014\n\010END_CALL\020\005\"\245" +
"\004\n\024ConfigurationMessage\022E\n\014closedGroups\030" +
"\001 \003(\0132/.signalservice.ConfigurationMessa" +
"ge.ClosedGroup\022\022\n\nopenGroups\030\002 \003(\t\022\023\n\013di" +
"splayName\030\003 \001(\t\022\026\n\016profilePicture\030\004 \001(\t\022" +
"\022\n\nprofileKey\030\005 \001(\014\022=\n\010contacts\030\006 \003(\0132+." +
"signalservice.ConfigurationMessage.Conta" +
"ct\032\233\001\n\013ClosedGroup\022\021\n\tpublicKey\030\001 \001(\014\022\014\n",
"\004name\030\002 \001(\t\0221\n\021encryptionKeyPair\030\003 \001(\0132\026" +
".signalservice.KeyPair\022\017\n\007members\030\004 \003(\014\022" +
"\016\n\006admins\030\005 \003(\014\022\027\n\017expirationTimer\030\006 \001(\r" +
"\032\223\001\n\007Contact\022\021\n\tpublicKey\030\001 \002(\014\022\014\n\004name\030" +
"\002 \002(\t\022\026\n\016profilePicture\030\003 \001(\t\022\022\n\nprofile" +
"Key\030\004 \001(\014\022\022\n\nisApproved\030\005 \001(\010\022\021\n\tisBlock" +
"ed\030\006 \001(\010\022\024\n\014didApproveMe\030\007 \001(\010\"y\n\026Messag" +
"eRequestResponse\022\022\n\nisApproved\030\001 \002(\010\022\022\n\n" +
"profileKey\030\002 \001(\014\0227\n\007profile\030\003 \001(\0132&.sign" +
"alservice.DataMessage.LokiProfile\"\375\001\n\023Sh",
"aredConfigMessage\0225\n\004kind\030\001 \002(\0162\'.signal" +
"service.SharedConfigMessage.Kind\022\r\n\005seqn" +
"o\030\002 \002(\003\022\014\n\004data\030\003 \002(\014\"\221\001\n\004Kind\022\020\n\014USER_P" +
"ROFILE\020\001\022\014\n\010CONTACTS\020\002\022\027\n\023CONVO_INFO_VOL" +
"ATILE\020\003\022\n\n\006GROUPS\020\004\022\025\n\021CLOSED_GROUP_INFO" +
"\020\005\022\030\n\024CLOSED_GROUP_MEMBERS\020\006\022\023\n\017ENCRYPTI" +
"ON_KEYS\020\007\"u\n\016ReceiptMessage\0220\n\004type\030\001 \002(" +
"\0162\".signalservice.ReceiptMessage.Type\022\021\n" +
"\ttimestamp\030\002 \003(\004\"\036\n\004Type\022\014\n\010DELIVERY\020\000\022\010" +
"\n\004READ\020\001\"\354\001\n\021AttachmentPointer\022\n\n\002id\030\001 \002",
"(\006\022\023\n\013contentType\030\002 \001(\t\022\013\n\003key\030\003 \001(\014\022\014\n\004" +
"size\030\004 \001(\r\022\021\n\tthumbnail\030\005 \001(\014\022\016\n\006digest\030" +
"\006 \001(\014\022\020\n\010fileName\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r" +
"\n\005width\030\t \001(\r\022\016\n\006height\030\n \001(\r\022\017\n\007caption" +
"\030\013 \001(\t\022\013\n\003url\030e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_ME" +
"SSAGE\020\001B3\n\034org.session.libsignal.protosB" +
"\023SignalServiceProtos"
"MemberLeftMessage\0326\n GroupUpdateInviteRe" +
"sponseMessage\022\022\n\nisApproved\030\001 \002(\010\032Y\n%Gro" +
"upUpdateDeleteMemberContentMessage\022\030\n\020me" +
"mberPublicKeys\030\001 \003(\014\022\026\n\016adminSignature\030\002" +
" \002(\014\032\203\005\n\031ClosedGroupControlMessage\022G\n\004ty" +
"pe\030\001 \002(\01629.signalservice.DataMessage.Clo",
"sedGroupControlMessage.Type\022\021\n\tpublicKey" +
"\030\002 \001(\014\022\014\n\004name\030\003 \001(\t\0221\n\021encryptionKeyPai" +
"r\030\004 \001(\0132\026.signalservice.KeyPair\022\017\n\007membe" +
"rs\030\005 \003(\014\022\016\n\006admins\030\006 \003(\014\022U\n\010wrappers\030\007 \003" +
"(\0132C.signalservice.DataMessage.ClosedGro" +
"upControlMessage.KeyPairWrapper\022\027\n\017expir" +
"ationTimer\030\010 \001(\r\022\030\n\020memberPrivateKey\030\t \001" +
"(\014\022\022\n\nprivateKey\030\n \001(\014\032=\n\016KeyPairWrapper" +
"\022\021\n\tpublicKey\030\001 \002(\014\022\030\n\020encryptedKeyPair\030" +
"\002 \002(\014\"\312\001\n\004Type\022\007\n\003NEW\020\001\022\027\n\023ENCRYPTION_KE",
"Y_PAIR\020\003\022\017\n\013NAME_CHANGE\020\004\022\021\n\rMEMBERS_ADD" +
"ED\020\005\022\023\n\017MEMBERS_REMOVED\020\006\022\017\n\013MEMBER_LEFT" +
"\020\007\022\n\n\006INVITE\020\t\022\013\n\007PROMOTE\020\n\022\020\n\014DELETE_GR" +
"OUP\020\013\022\023\n\017DELETE_MESSAGES\020\014\022\026\n\022DELETE_ATT" +
"ACHMENTS\020\r\032\222\001\n\010Reaction\022\n\n\002id\030\001 \002(\004\022\016\n\006a" +
"uthor\030\002 \002(\t\022\r\n\005emoji\030\003 \001(\t\022:\n\006action\030\004 \002" +
"(\0162*.signalservice.DataMessage.Reaction." +
"Action\"\037\n\006Action\022\t\n\005REACT\020\000\022\n\n\006REMOVE\020\001\"" +
"$\n\005Flags\022\033\n\027EXPIRATION_TIMER_UPDATE\020\002\"B\n" +
"\022GroupDeleteMessage\022\021\n\tpublicKey\030\001 \002(\014\022\031",
"\n\021lastEncryptionKey\030\002 \002(\014\"\030\n\026GroupMember" +
"LeftMessage\"O\n\022GroupInviteMessage\022\021\n\tpub" +
"licKey\030\001 \002(\014\022\014\n\004name\030\002 \002(\t\022\030\n\020memberPriv" +
"ateKey\030\003 \002(\014\"E\n\023GroupPromoteMessage\022\021\n\tp" +
"ublicKey\030\001 \002(\014\022\033\n\023encryptedPrivateKey\030\002 " +
"\002(\014\"\352\001\n\013CallMessage\022-\n\004type\030\001 \002(\0162\037.sign" +
"alservice.CallMessage.Type\022\014\n\004sdps\030\002 \003(\t" +
"\022\027\n\017sdpMLineIndexes\030\003 \003(\r\022\017\n\007sdpMids\030\004 \003" +
"(\t\022\014\n\004uuid\030\005 \002(\t\"f\n\004Type\022\r\n\tPRE_OFFER\020\006\022" +
"\t\n\005OFFER\020\001\022\n\n\006ANSWER\020\002\022\026\n\022PROVISIONAL_AN",
"SWER\020\003\022\022\n\016ICE_CANDIDATES\020\004\022\014\n\010END_CALL\020\005" +
"\"\245\004\n\024ConfigurationMessage\022E\n\014closedGroup" +
"s\030\001 \003(\0132/.signalservice.ConfigurationMes" +
"sage.ClosedGroup\022\022\n\nopenGroups\030\002 \003(\t\022\023\n\013" +
"displayName\030\003 \001(\t\022\026\n\016profilePicture\030\004 \001(" +
"\t\022\022\n\nprofileKey\030\005 \001(\014\022=\n\010contacts\030\006 \003(\0132" +
"+.signalservice.ConfigurationMessage.Con" +
"tact\032\233\001\n\013ClosedGroup\022\021\n\tpublicKey\030\001 \001(\014\022" +
"\014\n\004name\030\002 \001(\t\0221\n\021encryptionKeyPair\030\003 \001(\013" +
"2\026.signalservice.KeyPair\022\017\n\007members\030\004 \003(",
"\014\022\016\n\006admins\030\005 \003(\014\022\027\n\017expirationTimer\030\006 \001" +
"(\r\032\223\001\n\007Contact\022\021\n\tpublicKey\030\001 \002(\014\022\014\n\004nam" +
"e\030\002 \002(\t\022\026\n\016profilePicture\030\003 \001(\t\022\022\n\nprofi" +
"leKey\030\004 \001(\014\022\022\n\nisApproved\030\005 \001(\010\022\021\n\tisBlo" +
"cked\030\006 \001(\010\022\024\n\014didApproveMe\030\007 \001(\010\"y\n\026Mess" +
"ageRequestResponse\022\022\n\nisApproved\030\001 \002(\010\022\022" +
"\n\nprofileKey\030\002 \001(\014\0227\n\007profile\030\003 \001(\0132&.si" +
"gnalservice.DataMessage.LokiProfile\"\375\001\n\023" +
"SharedConfigMessage\0225\n\004kind\030\001 \002(\0162\'.sign" +
"alservice.SharedConfigMessage.Kind\022\r\n\005se",
"qno\030\002 \002(\003\022\014\n\004data\030\003 \002(\014\"\221\001\n\004Kind\022\020\n\014USER" +
"_PROFILE\020\001\022\014\n\010CONTACTS\020\002\022\027\n\023CONVO_INFO_V" +
"OLATILE\020\003\022\n\n\006GROUPS\020\004\022\025\n\021CLOSED_GROUP_IN" +
"FO\020\005\022\030\n\024CLOSED_GROUP_MEMBERS\020\006\022\023\n\017ENCRYP" +
"TION_KEYS\020\007\"u\n\016ReceiptMessage\0220\n\004type\030\001 " +
"\002(\0162\".signalservice.ReceiptMessage.Type\022" +
"\021\n\ttimestamp\030\002 \003(\004\"\036\n\004Type\022\014\n\010DELIVERY\020\000" +
"\022\010\n\004READ\020\001\"\354\001\n\021AttachmentPointer\022\n\n\002id\030\001" +
" \002(\006\022\023\n\013contentType\030\002 \001(\t\022\013\n\003key\030\003 \001(\014\022\014" +
"\n\004size\030\004 \001(\r\022\021\n\tthumbnail\030\005 \001(\014\022\016\n\006diges",
"t\030\006 \001(\014\022\020\n\010fileName\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r" +
"\022\r\n\005width\030\t \001(\r\022\016\n\006height\030\n \001(\r\022\017\n\007capti" +
"on\030\013 \001(\t\022\013\n\003url\030e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_" +
"MESSAGE\020\001B3\n\034org.session.libsignal.proto" +
"sB\023SignalServiceProtos"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@ -36040,7 +35762,7 @@ public final class SignalServiceProtos {
internal_static_signalservice_DataMessage_GroupUpdateInviteResponseMessage_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_signalservice_DataMessage_GroupUpdateInviteResponseMessage_descriptor,
new java.lang.String[] { "IsApproved", "ProfileKey", "Profile", });
new java.lang.String[] { "IsApproved", });
internal_static_signalservice_DataMessage_GroupUpdateDeleteMemberContentMessage_descriptor =
internal_static_signalservice_DataMessage_descriptor.getNestedTypes().get(12);
internal_static_signalservice_DataMessage_GroupUpdateDeleteMemberContentMessage_fieldAccessorTable = new