]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java
Send remote delete (#593)
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / helper / UnidentifiedAccessHelper.java
1 package org.asamk.signal.manager.helper;
2
3 import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
4 import org.whispersystems.libsignal.util.guava.Optional;
5 import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
6 import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
7 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
8
9 import java.util.Collection;
10 import java.util.List;
11 import java.util.stream.Collectors;
12
13 import static org.whispersystems.signalservice.internal.util.Util.getSecretBytes;
14
15 public class UnidentifiedAccessHelper {
16
17 private final SelfProfileKeyProvider selfProfileKeyProvider;
18
19 private final ProfileKeyProvider profileKeyProvider;
20
21 private final ProfileProvider profileProvider;
22
23 private final UnidentifiedAccessSenderCertificateProvider senderCertificateProvider;
24
25 public UnidentifiedAccessHelper(
26 final SelfProfileKeyProvider selfProfileKeyProvider,
27 final ProfileKeyProvider profileKeyProvider,
28 final ProfileProvider profileProvider,
29 final UnidentifiedAccessSenderCertificateProvider senderCertificateProvider
30 ) {
31 this.selfProfileKeyProvider = selfProfileKeyProvider;
32 this.profileKeyProvider = profileKeyProvider;
33 this.profileProvider = profileProvider;
34 this.senderCertificateProvider = senderCertificateProvider;
35 }
36
37 private byte[] getSelfUnidentifiedAccessKey() {
38 return UnidentifiedAccess.deriveAccessKeyFrom(selfProfileKeyProvider.getProfileKey());
39 }
40
41 public byte[] getTargetUnidentifiedAccessKey(SignalServiceAddress recipient) {
42 var theirProfileKey = profileKeyProvider.getProfileKey(recipient);
43 if (theirProfileKey == null) {
44 return null;
45 }
46
47 var targetProfile = profileProvider.getProfile(recipient);
48 if (targetProfile == null || targetProfile.getUnidentifiedAccess() == null) {
49 return null;
50 }
51
52 if (targetProfile.isUnrestrictedUnidentifiedAccess()) {
53 return createUnrestrictedUnidentifiedAccess();
54 }
55
56 return UnidentifiedAccess.deriveAccessKeyFrom(theirProfileKey);
57 }
58
59 public Optional<UnidentifiedAccessPair> getAccessForSync() {
60 var selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey();
61 var selfUnidentifiedAccessCertificate = senderCertificateProvider.getSenderCertificate();
62
63 if (selfUnidentifiedAccessKey == null || selfUnidentifiedAccessCertificate == null) {
64 return Optional.absent();
65 }
66
67 try {
68 return Optional.of(new UnidentifiedAccessPair(new UnidentifiedAccess(selfUnidentifiedAccessKey,
69 selfUnidentifiedAccessCertificate),
70 new UnidentifiedAccess(selfUnidentifiedAccessKey, selfUnidentifiedAccessCertificate)));
71 } catch (InvalidCertificateException e) {
72 return Optional.absent();
73 }
74 }
75
76 public List<Optional<UnidentifiedAccessPair>> getAccessFor(Collection<SignalServiceAddress> recipients) {
77 return recipients.stream().map(this::getAccessFor).collect(Collectors.toList());
78 }
79
80 public Optional<UnidentifiedAccessPair> getAccessFor(SignalServiceAddress recipient) {
81 var recipientUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipient);
82 var selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey();
83 var selfUnidentifiedAccessCertificate = senderCertificateProvider.getSenderCertificate();
84
85 if (recipientUnidentifiedAccessKey == null
86 || selfUnidentifiedAccessKey == null
87 || selfUnidentifiedAccessCertificate == null) {
88 return Optional.absent();
89 }
90
91 try {
92 return Optional.of(new UnidentifiedAccessPair(new UnidentifiedAccess(recipientUnidentifiedAccessKey,
93 selfUnidentifiedAccessCertificate),
94 new UnidentifiedAccess(selfUnidentifiedAccessKey, selfUnidentifiedAccessCertificate)));
95 } catch (InvalidCertificateException e) {
96 return Optional.absent();
97 }
98 }
99
100 private static byte[] createUnrestrictedUnidentifiedAccess() {
101 return getSecretBytes(16);
102 }
103 }