diff --git a/ts/components/conversation/message/message-content/MessageAvatar.tsx b/ts/components/conversation/message/message-content/MessageAvatar.tsx
index 220091961..85e71eb6c 100644
--- a/ts/components/conversation/message/message-content/MessageAvatar.tsx
+++ b/ts/components/conversation/message/message-content/MessageAvatar.tsx
@@ -6,7 +6,7 @@ import { MessageRenderingProps } from '../../../../models/messageType';
import { findCachedBlindedMatchOrLookItUp } from '../../../../session/apis/open_group_api/sogsv3/knownBlindedkeys';
import { getConversationController } from '../../../../session/conversations';
import { getSodiumRenderer } from '../../../../session/crypto';
-import { PubKey } from '../../../../session/types';
+import { KeyPrefixType, PubKey } from '../../../../session/types';
import { openConversationWithMessages } from '../../../../state/ducks/conversations';
import { updateUserDetailsModal } from '../../../../state/ducks/modalDialog';
import {
@@ -61,7 +61,7 @@ export const MessageAvatar = (props: Props) => {
const userName = authorName || authorProfileName || sender;
const onMessageAvatarClick = useCallback(async () => {
- if (isPublic && !PubKey.hasBlindedPrefix(sender)) {
+ if (isPublic && !PubKey.isBlinded(sender)) {
// public chat but session id not blinded. disable showing user details if we do not have an active convo with that user.
// an unactive convo with that user means that we never chatted with that id directyly, but only through a sogs
const convoWithSender = getConversationController().get(sender);
@@ -84,6 +84,11 @@ export const MessageAvatar = (props: Props) => {
}
if (isPublic && selectedConvoKey) {
+ if (sender.startsWith(KeyPrefixType.blinded25)) {
+ window.log.info('onMessageAvatarClick: blinded25 convo click are disabled currently...');
+
+ return;
+ }
const convoOpen = getConversationController().get(selectedConvoKey);
const room = OpenGroupData.getV2OpenGroupRoom(convoOpen.id);
let privateConvoToOpen = sender;
diff --git a/ts/components/menu/Menu.tsx b/ts/components/menu/Menu.tsx
index 695d0acf9..f00ae0b7a 100644
--- a/ts/components/menu/Menu.tsx
+++ b/ts/components/menu/Menu.tsx
@@ -357,7 +357,7 @@ export const CopyMenuItem = (): JSX.Element | null => {
export const MarkAllReadMenuItem = (): JSX.Element | null => {
const convoId = useConvoIdFromContext();
const isIncomingRequest = useIsIncomingRequest(convoId);
- if (!isIncomingRequest && !PubKey.hasBlindedPrefix(convoId)) {
+ if (!isIncomingRequest && !PubKey.isBlinded(convoId)) {
return (
- markAllReadByConvoId(convoId)}>{window.i18n('markAllAsRead')}
);
@@ -379,7 +379,7 @@ export const BlockMenuItem = (): JSX.Element | null => {
const isPrivate = useIsPrivate(convoId);
const isIncomingRequest = useIsIncomingRequest(convoId);
- if (!isMe && isPrivate && !isIncomingRequest && !PubKey.hasBlindedPrefix(convoId)) {
+ if (!isMe && isPrivate && !isIncomingRequest && !PubKey.isBlinded(convoId)) {
const blockTitle = isBlocked ? window.i18n('unblock') : window.i18n('block');
const blockHandler = isBlocked
? () => unblockConvoById(convoId)
diff --git a/ts/hooks/useParamSelector.ts b/ts/hooks/useParamSelector.ts
index 74ef78556..ba26cf208 100644
--- a/ts/hooks/useParamSelector.ts
+++ b/ts/hooks/useParamSelector.ts
@@ -101,7 +101,7 @@ export function useIsBlinded(convoId?: string) {
if (!convoId) {
return false;
}
- return Boolean(PubKey.hasBlindedPrefix(convoId));
+ return Boolean(PubKey.isBlinded(convoId));
}
export function useHasNickname(convoId?: string) {
diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts
index 9c745ac1f..1e793508e 100644
--- a/ts/models/conversation.ts
+++ b/ts/models/conversation.ts
@@ -532,8 +532,8 @@ export class ConversationModel extends Backbone.Model {
);
const hasIncomingMessages = incomingMessageCount > 0;
- if (this.id.startsWith('15')) {
- window.log.info('Sending a blinded message to this user: ', this.id);
+ if (PubKey.isBlinded(this.id)) {
+ window.log.info('Sending a blinded message react to this user: ', this.id);
await this.sendBlindedMessageRequest(chatMessageParams);
return;
}
@@ -1674,7 +1674,7 @@ export class ConversationModel extends Backbone.Model {
);
const hasIncomingMessages = incomingMessageCount > 0;
- if (this.id.startsWith('15')) {
+ if (PubKey.isBlinded(this.id)) {
window.log.info('Sending a blinded message to this user: ', this.id);
await this.sendBlindedMessageRequest(chatMessageParams);
return;
@@ -1778,7 +1778,7 @@ export class ConversationModel extends Backbone.Model {
const ourSignKeyBytes = await UserUtils.getUserED25519KeyPairBytes();
const groupUrl = this.getSogsOriginMessage();
- if (!PubKey.hasBlindedPrefix(this.id)) {
+ if (!PubKey.isBlinded(this.id)) {
window?.log?.warn('sendBlindedMessageRequest - convo is not a blinded one');
return;
}
@@ -1826,7 +1826,7 @@ export class ConversationModel extends Backbone.Model {
}
this.set({ active_at: Date.now(), isApproved: true });
-
+ // TODO we need to add support for sending blinded25 message request in addition to the legacy blinded15
await getMessageQueue().sendToOpenGroupV2BlindedRequest({
encryptedContent: encryptedMsg,
roomInfos: roomInfo,
diff --git a/ts/models/message.ts b/ts/models/message.ts
index f11167efd..592839993 100644
--- a/ts/models/message.ts
+++ b/ts/models/message.ts
@@ -1279,7 +1279,7 @@ export function findAndFormatContact(pubkey: string): FindAndFormatContactType {
if (
pubkey === UserUtils.getOurPubKeyStrFromCache() ||
- (pubkey && pubkey.startsWith('15') && isUsAnySogsFromCache(pubkey))
+ (pubkey && PubKey.isBlinded(pubkey) && isUsAnySogsFromCache(pubkey))
) {
profileName = window.i18n('you');
isMe = true;
diff --git a/ts/node/migration/sessionMigrations.ts b/ts/node/migration/sessionMigrations.ts
index 382cf9c18..365de0f9d 100644
--- a/ts/node/migration/sessionMigrations.ts
+++ b/ts/node/migration/sessionMigrations.ts
@@ -1676,7 +1676,7 @@ function updateToSessionSchemaVersion31(currentVersion: number, db: BetterSqlite
// this filter is based on the `isContactToStoreInWrapper` function. Note, blocked contacts won't be added to the wrapper at first, but will on the first start
const contactsToWriteInWrapper = db
.prepare(
- `SELECT * FROM ${CONVERSATIONS_TABLE} WHERE type = 'private' AND active_at > 0 AND priority <> ${CONVERSATION_PRIORITIES.hidden} AND (didApproveMe OR isApproved) AND id <> '$us' AND id NOT LIKE '15%' ;`
+ `SELECT * FROM ${CONVERSATIONS_TABLE} WHERE type = 'private' AND active_at > 0 AND priority <> ${CONVERSATION_PRIORITIES.hidden} AND (didApproveMe OR isApproved) AND id <> '$us' AND id NOT LIKE '15%' AND id NOT LIKE '25%' ;`
)
.all({
us: publicKeyHex,
diff --git a/ts/session/apis/open_group_api/sogsv3/knownBlindedkeys.ts b/ts/session/apis/open_group_api/sogsv3/knownBlindedkeys.ts
index bc23882ce..89297d34d 100644
--- a/ts/session/apis/open_group_api/sogsv3/knownBlindedkeys.ts
+++ b/ts/session/apis/open_group_api/sogsv3/knownBlindedkeys.ts
@@ -145,8 +145,8 @@ export function tryMatchBlindWithStandardKey(
throw new Error('standardKey must be a standard key (starting with 05)');
}
- if (!blindedSessionId.startsWith(KeyPrefixType.blinded)) {
- throw new Error('blindedKey must be a blinded key (starting with 15)');
+ if (!PubKey.isBlinded(blindedSessionId)) {
+ throw new Error('blindedKey must be a blinded key (starting with 15 or 25)');
}
// We don't want to stop iterating even if an error happens while looking for a blind/standard match.
@@ -204,7 +204,7 @@ function findNotCachedBlindingMatch(
// we iterate only over the convos private, approved, and which have an unblinded id.
const foundConvoMatchingBlindedPubkey = getConversationController()
.getConversations()
- .filter(m => m.isPrivate() && m.isApproved() && !PubKey.hasBlindedPrefix(m.id))
+ .filter(m => m.isPrivate() && m.isApproved() && !PubKey.isBlinded(m.id))
.find(m => {
return tryMatchBlindWithStandardKey(m.id, blindedId, serverPublicKey, sodium);
});
@@ -214,13 +214,13 @@ function findNotCachedBlindingMatch(
/**
* This function returns true if the given blindedId matches our own blinded id on any pysogs.
- * If the given pubkey is not blinded, it returns true if it is our naked SessionID.
+ * If the given pubkey is not blinded, it returns true if it is our naked SessionID.
* It can be used to replace mentions with the @You syntax and for the quotes too
*/
export function isUsAnySogsFromCache(blindedOrNakedId: string): boolean {
const usUnblinded = UserUtils.getOurPubKeyStrFromCache();
- if (!PubKey.hasBlindedPrefix(blindedOrNakedId)) {
+ if (!PubKey.isBlinded(blindedOrNakedId)) {
return blindedOrNakedId === usUnblinded;
}
const found = assertLoaded().find(
@@ -268,7 +268,7 @@ function findNotCachedBlindedConvoFromUnblindedKey(
serverPublicKey: string,
sodium: LibSodiumWrappers
): Array {
- if (PubKey.hasBlindedPrefix(unblindedID)) {
+ if (PubKey.isBlinded(unblindedID)) {
throw new Error(
'findNotCachedBlindedConvoFromUnblindedKey unblindedID is supposed to be unblinded!'
);
@@ -279,7 +279,7 @@ function findNotCachedBlindedConvoFromUnblindedKey(
const foundConvosForThisServerPk =
getConversationController()
.getConversations()
- .filter(m => m.isPrivate() && PubKey.hasBlindedPrefix(m.id) && m.isActive())
+ .filter(m => m.isPrivate() && PubKey.isBlinded(m.id) && m.isActive())
.filter(m => {
return tryMatchBlindWithStandardKey(unblindedID, m.id, serverPublicKey, sodium);
}) || [];
@@ -302,7 +302,7 @@ export async function findCachedBlindedMatchOrLookItUp(
serverPubKey: string,
sodium: LibSodiumWrappers
): Promise {
- if (!PubKey.hasBlindedPrefix(blindedId)) {
+ if (!PubKey.isBlinded(blindedId)) {
return blindedId;
}
const found = getCachedNakedKeyFromBlinded(blindedId, serverPubKey);
@@ -333,7 +333,7 @@ export function findCachedBlindedIdFromUnblinded(
unblindedId: string,
serverPubKey: string
): string | undefined {
- if (PubKey.hasBlindedPrefix(unblindedId)) {
+ if (PubKey.isBlinded(unblindedId)) {
throw new Error('findCachedBlindedIdFromUnblinded needs an unblindedID');
}
const found = assertLoaded().find(
@@ -351,7 +351,7 @@ export async function findCachedOurBlindedPubkeyOrLookItUp(
): Promise {
const ourNakedSessionID = UserUtils.getOurPubKeyStrFromCache();
- if (PubKey.hasBlindedPrefix(ourNakedSessionID)) {
+ if (PubKey.isBlinded(ourNakedSessionID)) {
throw new Error('findCachedBlindedIdFromUnblindedOrLookItUp needs a unblindedID');
}
let found = findCachedBlindedIdFromUnblinded(ourNakedSessionID, serverPubKey);
@@ -402,7 +402,7 @@ export function findCachedBlindedMatchOrLookupOnAllServers(
unblindedId: string,
sodium: LibSodiumWrappers
): Array {
- if (PubKey.hasBlindedPrefix(unblindedId)) {
+ if (PubKey.isBlinded(unblindedId)) {
throw new Error('findCachedBlindedMatchOrLookupOnAllServers needs an unblindedId');
}
diff --git a/ts/session/apis/open_group_api/sogsv3/sogsBlinding.ts b/ts/session/apis/open_group_api/sogsv3/sogsBlinding.ts
index 8e4aba24e..2f3318a6d 100644
--- a/ts/session/apis/open_group_api/sogsv3/sogsBlinding.ts
+++ b/ts/session/apis/open_group_api/sogsv3/sogsBlinding.ts
@@ -63,7 +63,8 @@ async function getOpenGroupHeaders(data: {
const blindingValues = getBlindingValues(serverPK, signingKeys, sodium);
ka = blindingValues.secretKey;
kA = blindingValues.publicKey;
- pubkey = `${KeyPrefixType.blinded}${toHex(kA)}`;
+ // TODO we will need to add the support of blinded25 here
+ pubkey = `${KeyPrefixType.blinded15}${toHex(kA)}`;
} else {
pubkey = `${KeyPrefixType.unblinded}${toHex(signingKeys.pubKeyBytes)}`;
}
@@ -151,7 +152,8 @@ const getBlindedPubKey = (
sodium: LibSodiumWrappers
): string => {
const blindedPubKeyBytes = getBlindingValues(serverPK, signingKeys, sodium);
- return `${KeyPrefixType.blinded}${to_hex(blindedPubKeyBytes.publicKey)}`;
+ // TODO we will need to add the support of blinded25 here
+ return `${KeyPrefixType.blinded15}${to_hex(blindedPubKeyBytes.publicKey)}`;
};
const getBlindingValues = (
diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts
index 6257b5599..b4b41d294 100644
--- a/ts/session/conversations/ConversationController.ts
+++ b/ts/session/conversations/ConversationController.ts
@@ -187,7 +187,7 @@ export class ConversationController {
'getConversationController().deleteBlindedContact() needs complete initial fetch'
);
}
- if (!PubKey.hasBlindedPrefix(blindedId)) {
+ if (!PubKey.isBlinded(blindedId)) {
throw new Error('deleteBlindedContact allow accepts blinded id');
}
window.log.info(`deleteBlindedContact with ${blindedId}`);
diff --git a/ts/session/sending/MessageQueue.ts b/ts/session/sending/MessageQueue.ts
index b7401fb78..af20d5391 100644
--- a/ts/session/sending/MessageQueue.ts
+++ b/ts/session/sending/MessageQueue.ts
@@ -139,7 +139,8 @@ export class MessageQueue {
recipientBlindedId: string;
}) {
try {
- if (!PubKey.hasBlindedPrefix(recipientBlindedId)) {
+ // TODO we will need to add the support for blinded25 messages requests
+ if (!PubKey.isBlinded(recipientBlindedId)) {
throw new Error('sendToOpenGroupV2BlindedRequest needs a blindedId');
}
const { serverTimestamp, serverId } = await MessageSender.sendToOpenGroupV2BlindedRequest(
diff --git a/ts/session/types/PubKey.ts b/ts/session/types/PubKey.ts
index 44654ebfb..987250d1c 100644
--- a/ts/session/types/PubKey.ts
+++ b/ts/session/types/PubKey.ts
@@ -10,9 +10,15 @@ export enum KeyPrefixType {
*/
standard = '05',
/**
- * used for participants in open groups
+ * used for participants in open groups (legacy blinding logic)
*/
- blinded = '15',
+ blinded15 = '15',
+
+ /**
+ * used for participants in open groups (new blinding logic)
+ */
+ blinded25 = '25',
+
/**
* used for participants in open groups
*/
@@ -32,7 +38,7 @@ export class PubKey {
public static readonly PREFIX_GROUP_TEXTSECURE = '__textsecure_group__!';
// prettier-ignore
private static readonly regex: RegExp = new RegExp(
- `^(${PubKey.PREFIX_GROUP_TEXTSECURE})?(${KeyPrefixType.standard}|${KeyPrefixType.blinded}|${KeyPrefixType.unblinded}|${KeyPrefixType.groupV3})?(${PubKey.HEX}{64}|${PubKey.HEX}{32})$`
+ `^(${PubKey.PREFIX_GROUP_TEXTSECURE})?(${KeyPrefixType.standard}|${KeyPrefixType.blinded15}|${KeyPrefixType.blinded25}|${KeyPrefixType.unblinded}|${KeyPrefixType.groupV3})?(${PubKey.HEX}{64}|${PubKey.HEX}{32})$`
);
/**
* If you want to update this regex. Be sure that those are matches ;
@@ -146,18 +152,19 @@ export class PubKey {
/**
* @param keyWithOrWithoutPrefix Key with or without prefix
- * @returns If key is the correct length and has a supported prefix 05 or 15
+ * @returns If key is the correct length and has a supported prefix 05, 15, 25
*/
public static isValidPrefixAndLength(keyWithOrWithoutPrefix: string): boolean {
return (
keyWithOrWithoutPrefix.length === 66 &&
- (keyWithOrWithoutPrefix.startsWith(KeyPrefixType.blinded) ||
+ (keyWithOrWithoutPrefix.startsWith(KeyPrefixType.blinded15) ||
+ keyWithOrWithoutPrefix.startsWith(KeyPrefixType.blinded25) ||
keyWithOrWithoutPrefix.startsWith(KeyPrefixType.standard))
);
}
/**
- * This removes the 05 or 15 prefix from a Pubkey which have it and have a length of 66
+ * This removes the 05, 15 or 25 prefix from a Pubkey which have it and have a length of 66
* @param keyWithOrWithoutPrefix the key with or without the prefix
*/
public static removePrefixIfNeeded(keyWithOrWithoutPrefix: string): string {
@@ -230,8 +237,8 @@ export class PubKey {
return fromHexToArray(PubKey.removePrefixIfNeeded(this.key));
}
- public static hasBlindedPrefix(key: string) {
- return key.startsWith(KeyPrefixType.blinded);
+ public static isBlinded(key: string) {
+ return key.startsWith(KeyPrefixType.blinded15) || key.startsWith(KeyPrefixType.blinded25);
}
public static isClosedGroupV3(key: string) {
diff --git a/ts/session/utils/libsession/libsession_utils_contacts.ts b/ts/session/utils/libsession/libsession_utils_contacts.ts
index a5d16d5df..00186a241 100644
--- a/ts/session/utils/libsession/libsession_utils_contacts.ts
+++ b/ts/session/utils/libsession/libsession_utils_contacts.ts
@@ -29,9 +29,7 @@ const mappedContactWrapperValues = new Map();
* We want to sync the message request status so we need to allow a contact even if it's not approved, did not approve us and is not blocked.
*/
function isContactToStoreInWrapper(convo: ConversationModel): boolean {
- return (
- !convo.isMe() && convo.isPrivate() && convo.isActive() && !PubKey.hasBlindedPrefix(convo.id)
- );
+ return !convo.isMe() && convo.isPrivate() && convo.isActive() && !PubKey.isBlinded(convo.id);
}
/**
diff --git a/ts/session/utils/sync/syncUtils.ts b/ts/session/utils/sync/syncUtils.ts
index cf0d7f3d9..e1d3ace6c 100644
--- a/ts/session/utils/sync/syncUtils.ts
+++ b/ts/session/utils/sync/syncUtils.ts
@@ -204,7 +204,7 @@ const getValidContacts = (convos: Array) => {
c.getRealSessionUsername() &&
c.isPrivate() &&
c.isApproved() &&
- !PubKey.hasBlindedPrefix(c.get('id'))
+ !PubKey.isBlinded(c.get('id'))
);
const contacts = contactsModels.map(c => {
diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts
index c7c1a3d61..97a4f4904 100644
--- a/ts/state/selectors/conversations.ts
+++ b/ts/state/selectors/conversations.ts
@@ -785,7 +785,7 @@ export const getMessageQuoteProps = createSelector(
const isFromMe = isUsAnySogsFromCache(author) || false;
// NOTE the quote lookup map always stores our messages using the unblinded pubkey
- if (isFromMe && PubKey.hasBlindedPrefix(author)) {
+ if (isFromMe && PubKey.isBlinded(author)) {
author = UserUtils.getOurPubKeyStrFromCache();
}
diff --git a/ts/test/session/unit/sogsv3/knownBlindedKeys_test.ts b/ts/test/session/unit/sogsv3/knownBlindedKeys_test.ts
index 3618c0eb4..022848ae7 100644
--- a/ts/test/session/unit/sogsv3/knownBlindedKeys_test.ts
+++ b/ts/test/session/unit/sogsv3/knownBlindedKeys_test.ts
@@ -418,7 +418,7 @@ describe('knownBlindedKeys', () => {
it('throws if blindedSessionId is not standard', () => {
expect(() => {
tryMatchBlindWithStandardKey(realSessionId, realSessionId, serverPublicKey, sodium);
- }).to.throw('blindedKey must be a blinded key (starting with 15)');
+ }).to.throw('blindedKey must be a blinded key (starting with 15 or 25)');
});
it('returns true if those keys are not matching blind & naked', () => {
diff --git a/ts/webworker/workers/node/util/util.worker.ts b/ts/webworker/workers/node/util/util.worker.ts
index 54e4daf54..f0ab356e9 100644
--- a/ts/webworker/workers/node/util/util.worker.ts
+++ b/ts/webworker/workers/node/util/util.worker.ts
@@ -141,7 +141,8 @@ async function verifySignature(
}
const messageData = fromBase64ToUint8Array(messageBase64);
const signature = fromBase64ToUint8Array(signatureBase64);
- const isBlindedSender = senderPubKey.startsWith('15');
+ // blinded15 or blinded25 are the same for the verifySignature logic
+ const isBlindedSender = senderPubKey.startsWith('15') || senderPubKey.startsWith('25');
const pubkeyWithoutPrefix = senderPubKey.slice(2);
const pubkeyBytes = fromHexToArray(pubkeyWithoutPrefix);