1 package org
.asamk
.signal
.manager
.storage
.protocol
;
3 import com
.fasterxml
.jackson
.core
.JsonParser
;
4 import com
.fasterxml
.jackson
.databind
.DeserializationContext
;
5 import com
.fasterxml
.jackson
.databind
.JsonDeserializer
;
6 import com
.fasterxml
.jackson
.databind
.JsonNode
;
8 import org
.asamk
.signal
.manager
.api
.TrustLevel
;
9 import org
.asamk
.signal
.manager
.storage
.Utils
;
10 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientAddress
;
11 import org
.signal
.libsignal
.protocol
.IdentityKey
;
12 import org
.signal
.libsignal
.protocol
.IdentityKeyPair
;
13 import org
.signal
.libsignal
.protocol
.InvalidKeyException
;
14 import org
.slf4j
.Logger
;
15 import org
.slf4j
.LoggerFactory
;
16 import org
.whispersystems
.signalservice
.api
.push
.ServiceId
;
17 import org
.whispersystems
.signalservice
.api
.util
.UuidUtil
;
19 import java
.io
.IOException
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Base64
;
22 import java
.util
.Date
;
23 import java
.util
.List
;
24 import java
.util
.stream
.Collectors
;
26 public class LegacyJsonIdentityKeyStore
{
28 private final static Logger logger
= LoggerFactory
.getLogger(LegacyJsonIdentityKeyStore
.class);
30 private final List
<LegacyIdentityInfo
> identities
;
31 private final IdentityKeyPair identityKeyPair
;
32 private final int localRegistrationId
;
34 private LegacyJsonIdentityKeyStore(
35 final List
<LegacyIdentityInfo
> identities
, IdentityKeyPair identityKeyPair
, int localRegistrationId
37 this.identities
= identities
;
38 this.identityKeyPair
= identityKeyPair
;
39 this.localRegistrationId
= localRegistrationId
;
42 public List
<LegacyIdentityInfo
> getIdentities() {
43 return identities
.stream()
44 .map(LegacyIdentityInfo
::getAddress
)
45 .collect(Collectors
.toSet())
47 .map(this::getIdentity
)
51 public IdentityKeyPair
getIdentityKeyPair() {
52 return identityKeyPair
;
55 public int getLocalRegistrationId() {
56 return localRegistrationId
;
59 private LegacyIdentityInfo
getIdentity(RecipientAddress address
) {
61 LegacyIdentityInfo maxIdentity
= null;
62 for (var id
: this.identities
) {
63 if (!id
.getAddress().matches(address
)) {
67 final var time
= id
.getDateAdded().getTime();
68 if (maxIdentity
== null || maxDate
<= time
) {
76 public static class JsonIdentityKeyStoreDeserializer
extends JsonDeserializer
<LegacyJsonIdentityKeyStore
> {
79 public LegacyJsonIdentityKeyStore
deserialize(
80 JsonParser jsonParser
, DeserializationContext deserializationContext
81 ) throws IOException
{
82 JsonNode node
= jsonParser
.getCodec().readTree(jsonParser
);
84 var localRegistrationId
= node
.get("registrationId").asInt();
85 var identityKeyPair
= new IdentityKeyPair(Base64
.getDecoder().decode(node
.get("identityKey").asText()));
87 var identities
= new ArrayList
<LegacyIdentityInfo
>();
89 var trustedKeysNode
= node
.get("trustedKeys");
90 if (trustedKeysNode
.isArray()) {
91 for (var trustedKey
: trustedKeysNode
) {
92 var trustedKeyName
= trustedKey
.hasNonNull("name") ? trustedKey
.get("name").asText() : null;
94 if (UuidUtil
.isUuid(trustedKeyName
)) {
95 // Ignore identities that were incorrectly created with UUIDs as name
99 var uuid
= trustedKey
.hasNonNull("uuid")
100 ? UuidUtil
.parseOrNull(trustedKey
.get("uuid").asText())
102 final var address
= uuid
== null
103 ? Utils
.getRecipientAddressFromIdentifier(trustedKeyName
)
104 : new RecipientAddress(ServiceId
.from(uuid
), trustedKeyName
);
106 var id
= new IdentityKey(Base64
.getDecoder().decode(trustedKey
.get("identityKey").asText()), 0);
107 var trustLevel
= trustedKey
.hasNonNull("trustLevel") ? TrustLevel
.fromInt(trustedKey
.get(
108 "trustLevel").asInt()) : TrustLevel
.TRUSTED_UNVERIFIED
;
109 var added
= trustedKey
.hasNonNull("addedTimestamp") ?
new Date(trustedKey
.get("addedTimestamp")
110 .asLong()) : new Date();
111 identities
.add(new LegacyIdentityInfo(address
, id
, trustLevel
, added
));
112 } catch (InvalidKeyException e
) {
113 logger
.warn("Error while decoding key for {}: {}", trustedKeyName
, e
.getMessage());
118 return new LegacyJsonIdentityKeyStore(identities
, identityKeyPair
, localRegistrationId
);