Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/iNPUTmice/Conversations.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Gultsch <daniel@gultsch.de>2022-10-15 01:09:29 +0300
committerDaniel Gultsch <daniel@gultsch.de>2022-10-15 01:09:29 +0300
commit3378447f606024d89fc9f13ac5111c2cb0176ce9 (patch)
treea334f13320c1c089548faf75b97ba804c1d7a7f4
parent0cd416298da9ce3844c099486a482bd4f5fa1a8d (diff)
parse hash token names
-rw-r--r--src/main/java/eu/siacs/conversations/Config.java2
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java33
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/sasl/HashedToken.java114
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/sasl/HashedTokenSha256.java24
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java3
5 files changed, 172 insertions, 4 deletions
diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java
index 812f6ae10..27d1f1097 100644
--- a/src/main/java/eu/siacs/conversations/Config.java
+++ b/src/main/java/eu/siacs/conversations/Config.java
@@ -60,7 +60,7 @@ public final class Config {
public static final long CONTACT_SYNC_RETRY_INTERVAL = 1000L * 60 * 5;
- public static final boolean QUICKSTART_ENABLED = true;
+ public static final boolean QUICKSTART_ENABLED = false;
//Notification settings
public static final boolean HIDE_MESSAGE_TEXT_IN_NOTIFICATION = false;
diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java
index fb1255566..26f9c9da0 100644
--- a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java
+++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java
@@ -6,7 +6,9 @@ import com.google.common.base.CaseFormat;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
+import com.google.common.collect.BiMap;
import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableBiMap;
import java.util.Arrays;
import java.util.Collection;
@@ -23,6 +25,16 @@ public enum ChannelBinding {
TLS_SERVER_END_POINT,
TLS_UNIQUE;
+ public static final BiMap<ChannelBinding, String> SHORT_NAMES;
+
+ static {
+ final ImmutableBiMap.Builder<ChannelBinding, String> builder = ImmutableBiMap.builder();
+ for (final ChannelBinding cb : values()) {
+ builder.put(cb, shortName(cb));
+ }
+ SHORT_NAMES = builder.build();
+ }
+
public static Collection<ChannelBinding> of(final Element channelBinding) {
Preconditions.checkArgument(
channelBinding == null
@@ -85,7 +97,24 @@ public enum ChannelBinding {
}
}
- public static boolean ensureBest(final ChannelBinding channelBinding, final SSLSockets.Version sslVersion) {
- return ChannelBinding.best(Collections.singleton(channelBinding), sslVersion) == channelBinding;
+ public static boolean ensureBest(
+ final ChannelBinding channelBinding, final SSLSockets.Version sslVersion) {
+ return ChannelBinding.best(Collections.singleton(channelBinding), sslVersion)
+ == channelBinding;
+ }
+
+ private static String shortName(final ChannelBinding channelBinding) {
+ switch (channelBinding) {
+ case TLS_UNIQUE:
+ return "UNIQ";
+ case TLS_EXPORTER:
+ return "EXPR";
+ case TLS_SERVER_END_POINT:
+ return "ENDP";
+ case NONE:
+ return "NONE";
+ default:
+ throw new AssertionError("Missing short name for " + channelBinding);
+ }
}
}
diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/HashedToken.java b/src/main/java/eu/siacs/conversations/crypto/sasl/HashedToken.java
new file mode 100644
index 000000000..f973c8377
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/crypto/sasl/HashedToken.java
@@ -0,0 +1,114 @@
+package eu.siacs.conversations.crypto.sasl;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.hash.HashFunction;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import javax.net.ssl.SSLSocket;
+
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.utils.SSLSockets;
+
+public abstract class HashedToken extends SaslMechanism {
+
+ private static List<String> HASH_FUNCTIONS = Arrays.asList("SHA-512", "SHA-256");
+
+ protected final ChannelBinding channelBinding;
+
+ protected HashedToken(final Account account, final ChannelBinding channelBinding) {
+ super(account);
+ this.channelBinding = channelBinding;
+ }
+
+ @Override
+ public int getPriority() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getClientFirstMessage() {
+ return null; // HMAC(token, "Initiator" || cb-data)
+ }
+
+ @Override
+ public String getResponse(final String challenge, final SSLSocket socket)
+ throws AuthenticationException {
+ // todo verify that challenge matches HMAC(token, "Responder" || cb-data)
+ return null;
+ }
+
+ protected abstract HashFunction getHashFunction(final byte[] key);
+
+ public static final class Mechanism {
+ public final String hashFunction;
+ public final ChannelBinding channelBinding;
+
+ public Mechanism(String hashFunction, ChannelBinding channelBinding) {
+ this.hashFunction = hashFunction;
+ this.channelBinding = channelBinding;
+ }
+
+ public static Mechanism of(final String mechanism) {
+ final int first = mechanism.indexOf('-');
+ final int last = mechanism.lastIndexOf('-');
+ if (last <= first || mechanism.length() <= last) {
+ throw new IllegalArgumentException("Not a valid HashedToken name");
+ }
+ if (mechanism.substring(0, first).equals("HT")) {
+ final String hashFunction = mechanism.substring(first + 1, last);
+ final String cbShortName = mechanism.substring(last + 1);
+ final ChannelBinding channelBinding =
+ ChannelBinding.SHORT_NAMES.inverse().get(cbShortName);
+ if (channelBinding == null) {
+ throw new IllegalArgumentException("Unknown channel binding " + cbShortName);
+ }
+ return new Mechanism(hashFunction, channelBinding);
+ } else {
+ throw new IllegalArgumentException("HashedToken name does not start with HT");
+ }
+ }
+
+ public static Multimap<String, ChannelBinding> of(final Collection<String> mechanisms) {
+ final ImmutableMultimap.Builder<String, ChannelBinding> builder =
+ ImmutableMultimap.builder();
+ for (final String name : mechanisms) {
+ try {
+ final Mechanism mechanism = Mechanism.of(name);
+ builder.put(mechanism.hashFunction, mechanism.channelBinding);
+ } catch (final IllegalArgumentException ignored) {
+ }
+ }
+ return builder.build();
+ }
+
+ public static Mechanism best(
+ final Collection<String> mechanisms, final SSLSockets.Version sslVersion) {
+ final Multimap<String, ChannelBinding> multimap = of(mechanisms);
+ for (final String hashFunction : HASH_FUNCTIONS) {
+ final Collection<ChannelBinding> channelBindings = multimap.get(hashFunction);
+ if (channelBindings.isEmpty()) {
+ continue;
+ }
+ final ChannelBinding cb = ChannelBinding.best(channelBindings, sslVersion);
+ return new Mechanism(hashFunction, cb);
+ }
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("hashFunction", hashFunction)
+ .add("channelBinding", channelBinding)
+ .toString();
+ }
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/HashedTokenSha256.java b/src/main/java/eu/siacs/conversations/crypto/sasl/HashedTokenSha256.java
new file mode 100644
index 000000000..fae756485
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/crypto/sasl/HashedTokenSha256.java
@@ -0,0 +1,24 @@
+package eu.siacs.conversations.crypto.sasl;
+
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hashing;
+
+import eu.siacs.conversations.entities.Account;
+
+public class HashedTokenSha256 extends HashedToken {
+
+ public HashedTokenSha256(final Account account, final ChannelBinding channelBinding) {
+ super(account, channelBinding);
+ }
+
+ @Override
+ protected HashFunction getHashFunction(final byte[] key) {
+ return Hashing.hmacSha256(key);
+ }
+
+ @Override
+ public String getMechanism() {
+ final String cbShortName = ChannelBinding.SHORT_NAMES.get(this.channelBinding);
+ return String.format("HT-SHA-256-%s", cbShortName);
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
index e693b2afa..f2b4c932a 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -63,6 +63,7 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.XmppDomainVerifier;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
import eu.siacs.conversations.crypto.sasl.ChannelBinding;
+import eu.siacs.conversations.crypto.sasl.HashedToken;
import eu.siacs.conversations.crypto.sasl.SaslMechanism;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Message;
@@ -1344,7 +1345,7 @@ public class XmppConnection implements Runnable {
final boolean sm = inline != null && inline.hasChild("sm", "urn:xmpp:sm:3");
final Element fast = inline == null ? null : inline.findChild("fast", Namespace.FAST);
final Collection<String> fastMechanisms = SaslMechanism.mechanisms(fast);
- Log.d(Config.LOGTAG,"fast mechanisms: "+fastMechanisms);
+ Log.d(Config.LOGTAG,"fast mechanism: "+ HashedToken.Mechanism.best(fastMechanisms, SSLSockets.version(this.socket)));
final Collection<String> bindFeatures = Bind2.features(inline);
quickStartAvailable =
sm