From 55d485de88bf2f67f64be3978cf7c5649f1cc36f Mon Sep 17 00:00:00 2001 From: AsamK Date: Fri, 8 Jul 2016 10:14:53 +0200 Subject: [PATCH] Add added timestamp to Identities --- src/main/java/org/asamk/signal/Hex.java | 22 ++++++++ .../asamk/signal/JsonIdentityKeyStore.java | 55 +++++++++++-------- .../java/org/asamk/signal/TrustLevel.java | 16 ++++++ 3 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 src/main/java/org/asamk/signal/Hex.java create mode 100644 src/main/java/org/asamk/signal/TrustLevel.java diff --git a/src/main/java/org/asamk/signal/Hex.java b/src/main/java/org/asamk/signal/Hex.java new file mode 100644 index 00000000..43d77cc5 --- /dev/null +++ b/src/main/java/org/asamk/signal/Hex.java @@ -0,0 +1,22 @@ +package org.asamk.signal; + +public class Hex { + + private final static char[] HEX_DIGITS = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + + public static String toStringCondensed(byte[] bytes) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < bytes.length; i++) { + appendHexChar(buf, bytes[i]); + } + return buf.toString(); + } + + private static void appendHexChar(StringBuffer buf, int b) { + buf.append(HEX_DIGITS[(b >> 4) & 0xf]); + buf.append(HEX_DIGITS[b & 0xf]); + buf.append(" "); + } +} diff --git a/src/main/java/org/asamk/signal/JsonIdentityKeyStore.java b/src/main/java/org/asamk/signal/JsonIdentityKeyStore.java index 332d8712..d4d0ea3e 100644 --- a/src/main/java/org/asamk/signal/JsonIdentityKeyStore.java +++ b/src/main/java/org/asamk/signal/JsonIdentityKeyStore.java @@ -10,10 +10,7 @@ import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.libsignal.state.IdentityKeyStore; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; class JsonIdentityKeyStore implements IdentityKeyStore { @@ -40,10 +37,18 @@ class JsonIdentityKeyStore implements IdentityKeyStore { @Override public void saveIdentity(String name, IdentityKey identityKey) { - saveIdentity(name, identityKey, TrustLevel.TRUSTED_UNVERIFIED); + saveIdentity(name, identityKey, TrustLevel.TRUSTED_UNVERIFIED, null); } - public void saveIdentity(String name, IdentityKey identityKey, TrustLevel trustLevel) { + /** + * Adds or updates the given identityKey for the user name and sets the trustLevel and added timestamp. + * + * @param name User name, i.e. phone number + * @param identityKey The user's public key + * @param trustLevel + * @param added Added timestamp, if null and the key is newly added, the current time is used. + */ + public void saveIdentity(String name, IdentityKey identityKey, TrustLevel trustLevel, Date added) { List identities = trustedKeys.get(name); if (identities == null) { identities = new ArrayList<>(); @@ -54,10 +59,13 @@ class JsonIdentityKeyStore implements IdentityKeyStore { continue; id.trustLevel = trustLevel; + if (added != null) { + id.added = added; + } return; } } - identities.add(new Identity(identityKey, trustLevel)); + identities.add(new Identity(identityKey, trustLevel, added != null ? added : new Date())); } @Override @@ -97,7 +105,8 @@ class JsonIdentityKeyStore implements IdentityKeyStore { try { IdentityKey id = new IdentityKey(Base64.decode(trustedKey.get("identityKey").asText()), 0); TrustLevel trustLevel = trustedKey.has("trustLevel") ? TrustLevel.fromInt(trustedKey.get("trustLevel").asInt()) : TrustLevel.TRUSTED_UNVERIFIED; - keyStore.saveIdentity(trustedKeyName, id, trustLevel); + Date added = trustedKey.has("addedTimestamp") ? new Date(trustedKey.get("addedTimestamp").asLong()) : new Date(); + keyStore.saveIdentity(trustedKeyName, id, trustLevel, added); } catch (InvalidKeyException | IOException e) { System.out.println(String.format("Error while decoding key for: %s", trustedKeyName)); } @@ -125,6 +134,7 @@ class JsonIdentityKeyStore implements IdentityKeyStore { json.writeStringField("name", trustedKey.getKey()); json.writeStringField("identityKey", Base64.encodeBytes(id.identityKey.serialize())); json.writeNumberField("trustLevel", id.trustLevel.ordinal()); + json.writeNumberField("addedTimestamp", id.added.getTime()); json.writeEndObject(); } } @@ -133,33 +143,30 @@ class JsonIdentityKeyStore implements IdentityKeyStore { } } - private enum TrustLevel { - UNTRUSTED, - TRUSTED_UNVERIFIED, - TRUSTED_VERIFIED; - - private static TrustLevel[] cachedValues = null; - - public static TrustLevel fromInt(int i) { - if (TrustLevel.cachedValues == null) { - TrustLevel.cachedValues = TrustLevel.values(); - } - return TrustLevel.cachedValues[i]; - } - } - - private class Identity { + public class Identity { IdentityKey identityKey; TrustLevel trustLevel; + Date added; public Identity(IdentityKey identityKey, TrustLevel trustLevel) { this.identityKey = identityKey; this.trustLevel = trustLevel; + this.added = new Date(); + } + + public Identity(IdentityKey identityKey, TrustLevel trustLevel, Date added) { + this.identityKey = identityKey; + this.trustLevel = trustLevel; + this.added = added; } public boolean isTrusted() { return trustLevel == TrustLevel.TRUSTED_UNVERIFIED || trustLevel == TrustLevel.TRUSTED_VERIFIED; } + + public String getFingerprint() { + return Hex.toStringCondensed(identityKey.getPublicKey().serialize()); + } } } diff --git a/src/main/java/org/asamk/signal/TrustLevel.java b/src/main/java/org/asamk/signal/TrustLevel.java new file mode 100644 index 00000000..e9e7796d --- /dev/null +++ b/src/main/java/org/asamk/signal/TrustLevel.java @@ -0,0 +1,16 @@ +package org.asamk.signal; + +public enum TrustLevel { + UNTRUSTED, + TRUSTED_UNVERIFIED, + TRUSTED_VERIFIED; + + private static TrustLevel[] cachedValues = null; + + public static TrustLevel fromInt(int i) { + if (TrustLevel.cachedValues == null) { + TrustLevel.cachedValues = TrustLevel.values(); + } + return TrustLevel.cachedValues[i]; + } +} -- 2.50.1