From ff28d72db67b332ea113115893f26c88b9f533dc Mon Sep 17 00:00:00 2001 From: Alan Evans Date: Fri, 1 May 2020 16:25:26 -0300 Subject: [PATCH] New GV2 internal prefix and scrubber. --- .../securesms/groups/GroupId.java | 29 ++++++++++++------- .../securesms/logsubmit/util/Scrubber.java | 29 ++++++++++++++----- .../securesms/groups/GroupIdTest.java | 19 +++++++----- .../logsubmit/util/ScrubberTest.java | 14 ++++++--- 4 files changed, 61 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupId.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupId.java index b3ce7cb3d8..56d1c02cf5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupId.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupId.java @@ -14,11 +14,12 @@ import java.security.SecureRandom; public abstract class GroupId { - private static final String ENCODED_SIGNAL_GROUP_PREFIX = "__textsecure_group__!"; - private static final String ENCODED_MMS_GROUP_PREFIX = "__signal_mms_group__!"; - private static final int MMS_BYTE_LENGTH = 16; - private static final int V1_MMS_BYTE_LENGTH = 16; - private static final int V2_BYTE_LENGTH = GroupIdentifier.SIZE; + private static final String ENCODED_SIGNAL_GROUP_V1_PREFIX = "__textsecure_group__!"; + private static final String ENCODED_SIGNAL_GROUP_V2_PREFIX = "__signal_group__v2__!"; + private static final String ENCODED_MMS_GROUP_PREFIX = "__signal_mms_group__!"; + private static final int MMS_BYTE_LENGTH = 16; + private static final int V1_MMS_BYTE_LENGTH = 16; + private static final int V2_BYTE_LENGTH = GroupIdentifier.SIZE; private final String encodedId; @@ -106,7 +107,11 @@ public abstract class GroupId { byte[] bytes = extractDecodedId(encodedGroupId); - return encodedGroupId.startsWith(ENCODED_MMS_GROUP_PREFIX) ? mms(bytes) : push(bytes); + if (encodedGroupId.startsWith(ENCODED_SIGNAL_GROUP_V2_PREFIX)) return v2(bytes); + else if (encodedGroupId.startsWith(ENCODED_SIGNAL_GROUP_V1_PREFIX)) return v1(bytes); + else if (encodedGroupId.startsWith(ENCODED_MMS_GROUP_PREFIX)) return mms(bytes); + + throw new BadGroupIdException(); } catch (IOException e) { throw new BadGroupIdException(e); } @@ -129,7 +134,9 @@ public abstract class GroupId { } public static boolean isEncodedGroup(@NonNull String groupId) { - return groupId.startsWith(ENCODED_SIGNAL_GROUP_PREFIX) || groupId.startsWith(ENCODED_MMS_GROUP_PREFIX); + return groupId.startsWith(ENCODED_SIGNAL_GROUP_V2_PREFIX) || + groupId.startsWith(ENCODED_SIGNAL_GROUP_V1_PREFIX) || + groupId.startsWith(ENCODED_MMS_GROUP_PREFIX); } private static byte[] extractDecodedId(@NonNull String encodedGroupId) throws IOException { @@ -220,8 +227,8 @@ public abstract class GroupId { } public static abstract class Push extends GroupId { - private Push(@NonNull byte[] bytes) { - super(ENCODED_SIGNAL_GROUP_PREFIX, bytes); + private Push(@NonNull String prefix, @NonNull byte[] bytes) { + super(prefix, bytes); } @Override @@ -238,7 +245,7 @@ public abstract class GroupId { public static final class V1 extends GroupId.Push { private V1(@NonNull byte[] bytes) { - super(bytes); + super(ENCODED_SIGNAL_GROUP_V1_PREFIX, bytes); } @Override @@ -255,7 +262,7 @@ public abstract class GroupId { public static final class V2 extends GroupId.Push { private V2(@NonNull byte[] bytes) { - super(bytes); + super(ENCODED_SIGNAL_GROUP_V2_PREFIX, bytes); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/util/Scrubber.java b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/util/Scrubber.java index 33a077c831..f230c6f5ff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/util/Scrubber.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/util/Scrubber.java @@ -17,8 +17,6 @@ package org.thoughtcrime.securesms.logsubmit.util; -import android.text.TextUtils; - import androidx.annotation.NonNull; import java.util.regex.Matcher; @@ -49,8 +47,14 @@ public final class Scrubber { /** * The middle group will be censored. */ - private static final Pattern GROUP_ID_PATTERN = Pattern.compile("(__)(textsecure_group__![^\\s]+)([^\\s]{2})"); - private static final String GROUP_ID_CENSOR = "...group..."; + private static final Pattern GROUP_ID_V1_PATTERN = Pattern.compile("(__)(textsecure_group__![^\\s]+)([^\\s]{2})"); + private static final String GROUP_ID_V1_CENSOR = "...group..."; + + /** + * The middle group will be censored. + */ + private static final Pattern GROUP_ID_V2_PATTERN = Pattern.compile("(__)(signal_group__v2__![^\\s]+)([^\\s]{2})"); + private static final String GROUP_ID_V2_CENSOR = "...group_v2..."; /** * The middle group will be censored. @@ -62,7 +66,8 @@ public final class Scrubber { in = scrubE164(in); in = scrubEmail(in); - in = scrubGroups(in); + in = scrubGroupsV1(in); + in = scrubGroupsV2(in); in = scrubUuids(in); return in; @@ -83,11 +88,19 @@ public final class Scrubber { .append(EMAIL_CENSOR)); } - private static CharSequence scrubGroups(@NonNull CharSequence in) { + private static CharSequence scrubGroupsV1(@NonNull CharSequence in) { return scrub(in, - GROUP_ID_PATTERN, + GROUP_ID_V1_PATTERN, (matcher, output) -> output.append(matcher.group(1)) - .append(GROUP_ID_CENSOR) + .append(GROUP_ID_V1_CENSOR) + .append(matcher.group(3))); + } + + private static CharSequence scrubGroupsV2(@NonNull CharSequence in) { + return scrub(in, + GROUP_ID_V2_PATTERN, + (matcher, output) -> output.append(matcher.group(1)) + .append(GROUP_ID_V2_CENSOR) .append(matcher.group(3))); } diff --git a/app/src/test/java/org/thoughtcrime/securesms/groups/GroupIdTest.java b/app/src/test/java/org/thoughtcrime/securesms/groups/GroupIdTest.java index 1ddc1b8002..90efd28f81 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/groups/GroupIdTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/groups/GroupIdTest.java @@ -45,7 +45,7 @@ public final class GroupIdTest { public void can_create_for_gv2_from_GroupIdentifier() throws IOException, InvalidInputException { GroupId.V2 groupId = GroupId.v2(new GroupIdentifier(Hex.fromStringCondensed("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))); - assertEquals("__textsecure_group__!0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", groupId.toString()); + assertEquals("__signal_group__v2__!0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", groupId.toString()); assertFalse(groupId.isMms()); assertFalse(groupId.isV1()); assertTrue(groupId.isV2()); @@ -58,7 +58,7 @@ public final class GroupIdTest { GroupId.V2 groupId = GroupId.v2(new GroupMasterKey(Hex.fromStringCondensed("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))); - assertEquals("__textsecure_group__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e", groupId.toString()); + assertEquals("__signal_group__v2__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e", groupId.toString()); assertFalse(groupId.isMms()); assertFalse(groupId.isV1()); assertTrue(groupId.isV2()); @@ -67,9 +67,9 @@ public final class GroupIdTest { @Test public void can_parse_gv2() throws IOException { - GroupId groupId = GroupId.parseOrThrow("__textsecure_group__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"); + GroupId groupId = GroupId.parseOrThrow("__signal_group__v2__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"); - assertEquals("__textsecure_group__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e", groupId.toString()); + assertEquals("__signal_group__v2__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e", groupId.toString()); assertArrayEquals(Hex.fromStringCondensed("9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"), groupId.getDecodedId()); assertFalse(groupId.isMms()); assertFalse(groupId.isV1()); @@ -145,6 +145,11 @@ public final class GroupIdTest { GroupId.parseOrThrow("__textsecure_group__!0001020305060708090b0c0d0e0fODD_HEX"); } + @Test(expected = BadGroupIdException.class) + public void bad_encoding__gv2_prefix_with_wrong_length() throws BadGroupIdException { + GroupId.parse("__signal_group__v2__!000102030405060708090a0b0c0d0e0f"); + } + @Test public void get_bytes() { byte[] bytes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; @@ -212,7 +217,7 @@ public final class GroupIdTest { @Test public void require_v2_and_push() { - GroupId groupId = GroupId.parseOrThrow("__textsecure_group__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"); + GroupId groupId = GroupId.parseOrThrow("__signal_group__v2__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"); GroupId.V2 v2 = groupId.requireV2(); GroupId.Push push = groupId.requirePush(); @@ -244,7 +249,7 @@ public final class GroupIdTest { @Test(expected = AssertionError.class) public void cannot_require_v1_of_v2() throws BadGroupIdException { - GroupId groupId = GroupId.parse("__textsecure_group__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"); + GroupId groupId = GroupId.parse("__signal_group__v2__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"); groupId.requireV1(); } @@ -298,6 +303,6 @@ public final class GroupIdTest { public void parse_bytes_to_v2_via_by_push() throws BadGroupIdException { GroupId.V2 v2 = GroupId.push(new byte[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }).requireV2(); - assertEquals("__textsecure_group__!000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f", v2.toString()); + assertEquals("__signal_group__v2__!000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f", v2.toString()); } } diff --git a/app/src/test/java/org/thoughtcrime/securesms/logsubmit/util/ScrubberTest.java b/app/src/test/java/org/thoughtcrime/securesms/logsubmit/util/ScrubberTest.java index 858156cce0..e2ec737cc3 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/logsubmit/util/ScrubberTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/logsubmit/util/ScrubberTest.java @@ -58,11 +58,17 @@ public final class ScrubberTest { { "An email and a number abc@def.com +155556789012345", "An email and a number a...@... +*************45" }, - { "__textsecure_group__!abcdefg1234567890", - "__...group...90" }, + { "__textsecure_group__!000102030405060708090a0b0c0d0e0f", + "__...group...0f" }, - { "A group id __textsecure_group__!abcdefg0987654321 surrounded with text", - "A group id __...group...21 surrounded with text" }, + { "A group id __textsecure_group__!000102030405060708090a0b0c0d0e1a surrounded with text", + "A group id __...group...1a surrounded with text" }, + + { "__signal_group__v2__!0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "__...group_v2...ef" }, + + { "A group v2 id __signal_group__v2__!23456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01 surrounded with text", + "A group v2 id __...group_v2...01 surrounded with text" }, { "a37cb654-c9e0-4c1e-93df-3d11ca3c97f4", "********-****-****-****-**********f4" },