mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 18:40:39 +00:00
Implement trustLevel for IdentityKeys
This commit is contained in:
parent
0f0d8a873a
commit
f2c2597379
1 changed files with 77 additions and 19 deletions
|
@ -10,12 +10,14 @@ import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.state.IdentityKeyStore;
|
import org.whispersystems.libsignal.state.IdentityKeyStore;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
class JsonIdentityKeyStore implements IdentityKeyStore {
|
class JsonIdentityKeyStore implements IdentityKeyStore {
|
||||||
|
|
||||||
private final Map<String, IdentityKey> trustedKeys = new HashMap<>();
|
private final Map<String, List<Identity>> trustedKeys = new HashMap<>();
|
||||||
|
|
||||||
private final IdentityKeyPair identityKeyPair;
|
private final IdentityKeyPair identityKeyPair;
|
||||||
private final int localRegistrationId;
|
private final int localRegistrationId;
|
||||||
|
@ -26,10 +28,6 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
|
||||||
this.localRegistrationId = localRegistrationId;
|
this.localRegistrationId = localRegistrationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTrustedKeys(Map<String, IdentityKey> keyMap) {
|
|
||||||
trustedKeys.putAll(keyMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentityKeyPair getIdentityKeyPair() {
|
public IdentityKeyPair getIdentityKeyPair() {
|
||||||
return identityKeyPair;
|
return identityKeyPair;
|
||||||
|
@ -42,13 +40,41 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveIdentity(String name, IdentityKey identityKey) {
|
public void saveIdentity(String name, IdentityKey identityKey) {
|
||||||
trustedKeys.put(name, identityKey);
|
saveIdentity(name, identityKey, TrustLevel.TRUSTED_UNVERIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveIdentity(String name, IdentityKey identityKey, TrustLevel trustLevel) {
|
||||||
|
List<Identity> identities = trustedKeys.get(name);
|
||||||
|
if (identities == null) {
|
||||||
|
identities = new ArrayList<>();
|
||||||
|
trustedKeys.put(name, identities);
|
||||||
|
} else {
|
||||||
|
for (Identity id : identities) {
|
||||||
|
if (!id.identityKey.equals(identityKey))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
id.trustLevel = trustLevel;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
identities.add(new Identity(identityKey, trustLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
|
public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
|
||||||
IdentityKey trusted = trustedKeys.get(name);
|
List<Identity> identities = trustedKeys.get(name);
|
||||||
return (trusted == null || trusted.equals(identityKey));
|
if (identities == null) {
|
||||||
|
// Trust on first use
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Identity id : identities) {
|
||||||
|
if (id.identityKey.equals(identityKey)) {
|
||||||
|
return id.isTrusted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class JsonIdentityKeyStoreDeserializer extends JsonDeserializer<JsonIdentityKeyStore> {
|
public static class JsonIdentityKeyStoreDeserializer extends JsonDeserializer<JsonIdentityKeyStore> {
|
||||||
|
@ -62,24 +88,23 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
|
||||||
IdentityKeyPair identityKeyPair = new IdentityKeyPair(Base64.decode(node.get("identityKey").asText()));
|
IdentityKeyPair identityKeyPair = new IdentityKeyPair(Base64.decode(node.get("identityKey").asText()));
|
||||||
|
|
||||||
|
|
||||||
Map<String, IdentityKey> trustedKeyMap = new HashMap<>();
|
JsonIdentityKeyStore keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId);
|
||||||
|
|
||||||
JsonNode trustedKeysNode = node.get("trustedKeys");
|
JsonNode trustedKeysNode = node.get("trustedKeys");
|
||||||
if (trustedKeysNode.isArray()) {
|
if (trustedKeysNode.isArray()) {
|
||||||
for (JsonNode trustedKey : trustedKeysNode) {
|
for (JsonNode trustedKey : trustedKeysNode) {
|
||||||
String trustedKeyName = trustedKey.get("name").asText();
|
String trustedKeyName = trustedKey.get("name").asText();
|
||||||
try {
|
try {
|
||||||
trustedKeyMap.put(trustedKeyName, new IdentityKey(Base64.decode(trustedKey.get("identityKey").asText()), 0));
|
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);
|
||||||
} catch (InvalidKeyException | IOException e) {
|
} catch (InvalidKeyException | IOException e) {
|
||||||
System.out.println(String.format("Error while decoding key for: %s", trustedKeyName));
|
System.out.println(String.format("Error while decoding key for: %s", trustedKeyName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonIdentityKeyStore keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId);
|
|
||||||
keyStore.addTrustedKeys(trustedKeyMap);
|
|
||||||
|
|
||||||
return keyStore;
|
return keyStore;
|
||||||
|
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
|
@ -94,14 +119,47 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
|
||||||
json.writeNumberField("registrationId", jsonIdentityKeyStore.getLocalRegistrationId());
|
json.writeNumberField("registrationId", jsonIdentityKeyStore.getLocalRegistrationId());
|
||||||
json.writeStringField("identityKey", Base64.encodeBytes(jsonIdentityKeyStore.getIdentityKeyPair().serialize()));
|
json.writeStringField("identityKey", Base64.encodeBytes(jsonIdentityKeyStore.getIdentityKeyPair().serialize()));
|
||||||
json.writeArrayFieldStart("trustedKeys");
|
json.writeArrayFieldStart("trustedKeys");
|
||||||
for (Map.Entry<String, IdentityKey> trustedKey : jsonIdentityKeyStore.trustedKeys.entrySet()) {
|
for (Map.Entry<String, List<Identity>> trustedKey : jsonIdentityKeyStore.trustedKeys.entrySet()) {
|
||||||
json.writeStartObject();
|
for (Identity id : trustedKey.getValue()) {
|
||||||
json.writeStringField("name", trustedKey.getKey());
|
json.writeStartObject();
|
||||||
json.writeStringField("identityKey", Base64.encodeBytes(trustedKey.getValue().serialize()));
|
json.writeStringField("name", trustedKey.getKey());
|
||||||
json.writeEndObject();
|
json.writeStringField("identityKey", Base64.encodeBytes(id.identityKey.serialize()));
|
||||||
|
json.writeNumberField("trustLevel", id.trustLevel.ordinal());
|
||||||
|
json.writeEndObject();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
json.writeEndArray();
|
json.writeEndArray();
|
||||||
json.writeEndObject();
|
json.writeEndObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
IdentityKey identityKey;
|
||||||
|
TrustLevel trustLevel;
|
||||||
|
|
||||||
|
public Identity(IdentityKey identityKey, TrustLevel trustLevel) {
|
||||||
|
this.identityKey = identityKey;
|
||||||
|
this.trustLevel = trustLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTrusted() {
|
||||||
|
return trustLevel == TrustLevel.TRUSTED_UNVERIFIED ||
|
||||||
|
trustLevel == TrustLevel.TRUSTED_VERIFIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue