1 package org
.asamk
.signal
.manager
.helper
;
3 import org
.asamk
.signal
.storage
.profiles
.SignalProfile
;
4 import org
.signal
.libsignal
.metadata
.certificate
.InvalidCertificateException
;
5 import org
.signal
.zkgroup
.profiles
.ProfileKey
;
6 import org
.whispersystems
.libsignal
.util
.guava
.Optional
;
7 import org
.whispersystems
.signalservice
.api
.crypto
.UnidentifiedAccess
;
8 import org
.whispersystems
.signalservice
.api
.crypto
.UnidentifiedAccessPair
;
9 import org
.whispersystems
.signalservice
.api
.push
.SignalServiceAddress
;
11 import java
.util
.Collection
;
12 import java
.util
.List
;
13 import java
.util
.stream
.Collectors
;
15 import static org
.whispersystems
.signalservice
.internal
.util
.Util
.getSecretBytes
;
17 public class UnidentifiedAccessHelper
{
19 private final SelfProfileKeyProvider selfProfileKeyProvider
;
21 private final ProfileKeyProvider profileKeyProvider
;
23 private final ProfileProvider profileProvider
;
25 private final UnidentifiedAccessSenderCertificateProvider senderCertificateProvider
;
27 public UnidentifiedAccessHelper(final SelfProfileKeyProvider selfProfileKeyProvider
, final ProfileKeyProvider profileKeyProvider
, final ProfileProvider profileProvider
, final UnidentifiedAccessSenderCertificateProvider senderCertificateProvider
) {
28 this.selfProfileKeyProvider
= selfProfileKeyProvider
;
29 this.profileKeyProvider
= profileKeyProvider
;
30 this.profileProvider
= profileProvider
;
31 this.senderCertificateProvider
= senderCertificateProvider
;
34 public byte[] getSelfUnidentifiedAccessKey() {
35 return UnidentifiedAccess
.deriveAccessKeyFrom(selfProfileKeyProvider
.getProfileKey());
38 public byte[] getTargetUnidentifiedAccessKey(SignalServiceAddress recipient
) {
39 ProfileKey theirProfileKey
= profileKeyProvider
.getProfileKey(recipient
);
40 if (theirProfileKey
== null) {
44 SignalProfile targetProfile
= profileProvider
.getProfile(recipient
);
45 if (targetProfile
== null || targetProfile
.getUnidentifiedAccess() == null) {
49 if (targetProfile
.isUnrestrictedUnidentifiedAccess()) {
50 return createUnrestrictedUnidentifiedAccess();
53 return UnidentifiedAccess
.deriveAccessKeyFrom(theirProfileKey
);
56 public Optional
<UnidentifiedAccessPair
> getAccessForSync() {
57 byte[] selfUnidentifiedAccessKey
= getSelfUnidentifiedAccessKey();
58 byte[] selfUnidentifiedAccessCertificate
= senderCertificateProvider
.getSenderCertificate();
60 if (selfUnidentifiedAccessKey
== null || selfUnidentifiedAccessCertificate
== null) {
61 return Optional
.absent();
65 return Optional
.of(new UnidentifiedAccessPair(
66 new UnidentifiedAccess(selfUnidentifiedAccessKey
, selfUnidentifiedAccessCertificate
),
67 new UnidentifiedAccess(selfUnidentifiedAccessKey
, selfUnidentifiedAccessCertificate
)
69 } catch (InvalidCertificateException e
) {
70 return Optional
.absent();
74 public List
<Optional
<UnidentifiedAccessPair
>> getAccessFor(Collection
<SignalServiceAddress
> recipients
) {
75 return recipients
.stream()
76 .map(this::getAccessFor
)
77 .collect(Collectors
.toList());
80 public Optional
<UnidentifiedAccessPair
> getAccessFor(SignalServiceAddress recipient
) {
81 byte[] recipientUnidentifiedAccessKey
= getTargetUnidentifiedAccessKey(recipient
);
82 byte[] selfUnidentifiedAccessKey
= getSelfUnidentifiedAccessKey();
83 byte[] selfUnidentifiedAccessCertificate
= senderCertificateProvider
.getSenderCertificate();
85 if (recipientUnidentifiedAccessKey
== null || selfUnidentifiedAccessKey
== null || selfUnidentifiedAccessCertificate
== null) {
86 return Optional
.absent();
90 return Optional
.of(new UnidentifiedAccessPair(
91 new UnidentifiedAccess(recipientUnidentifiedAccessKey
, selfUnidentifiedAccessCertificate
),
92 new UnidentifiedAccess(selfUnidentifiedAccessKey
, selfUnidentifiedAccessCertificate
)
94 } catch (InvalidCertificateException e
) {
95 return Optional
.absent();
99 private static byte[] createUnrestrictedUnidentifiedAccess() {
100 return getSecretBytes(16);