1 package org
.asamk
.signal
.manager
.helper
;
3 import org
.asamk
.signal
.manager
.config
.ServiceConfig
;
4 import org
.asamk
.signal
.manager
.internal
.SignalDependencies
;
5 import org
.asamk
.signal
.manager
.storage
.SignalAccount
;
6 import org
.asamk
.signal
.manager
.util
.KeyUtils
;
7 import org
.signal
.libsignal
.protocol
.IdentityKeyPair
;
8 import org
.signal
.libsignal
.protocol
.state
.PreKeyRecord
;
9 import org
.signal
.libsignal
.protocol
.state
.SignedPreKeyRecord
;
10 import org
.slf4j
.Logger
;
11 import org
.slf4j
.LoggerFactory
;
12 import org
.whispersystems
.signalservice
.api
.account
.PreKeyUpload
;
13 import org
.whispersystems
.signalservice
.api
.push
.ServiceIdType
;
15 import java
.io
.IOException
;
16 import java
.util
.List
;
18 public class PreKeyHelper
{
20 private final static Logger logger
= LoggerFactory
.getLogger(PreKeyHelper
.class);
22 private final SignalAccount account
;
23 private final SignalDependencies dependencies
;
26 final SignalAccount account
, final SignalDependencies dependencies
28 this.account
= account
;
29 this.dependencies
= dependencies
;
32 public void refreshPreKeysIfNecessary() throws IOException
{
33 refreshPreKeysIfNecessary(ServiceIdType
.ACI
);
34 refreshPreKeysIfNecessary(ServiceIdType
.PNI
);
37 public void refreshPreKeysIfNecessary(ServiceIdType serviceIdType
) throws IOException
{
38 final var preKeyCounts
= dependencies
.getAccountManager().getPreKeyCounts(serviceIdType
);
39 if (preKeyCounts
.getEcCount() < ServiceConfig
.PREKEY_MINIMUM_COUNT
) {
40 refreshPreKeys(serviceIdType
);
42 // TODO kyber pre keys
45 public void refreshPreKeys() throws IOException
{
46 refreshPreKeys(ServiceIdType
.ACI
);
47 refreshPreKeys(ServiceIdType
.PNI
);
50 public void refreshPreKeys(ServiceIdType serviceIdType
) throws IOException
{
51 final var identityKeyPair
= account
.getIdentityKeyPair(serviceIdType
);
52 if (identityKeyPair
== null) {
55 final var accountId
= account
.getAccountId(serviceIdType
);
56 if (accountId
== null) {
60 refreshPreKeys(serviceIdType
, identityKeyPair
);
61 } catch (Exception e
) {
62 logger
.warn("Failed to store new pre keys, resetting preKey id offset", e
);
63 account
.resetPreKeyOffsets(serviceIdType
);
64 refreshPreKeys(serviceIdType
, identityKeyPair
);
68 private void refreshPreKeys(
69 final ServiceIdType serviceIdType
, final IdentityKeyPair identityKeyPair
70 ) throws IOException
{
71 final var oneTimePreKeys
= generatePreKeys(serviceIdType
);
72 final var signedPreKeyRecord
= generateSignedPreKey(serviceIdType
, identityKeyPair
);
74 final var preKeyUpload
= new PreKeyUpload(serviceIdType
,
75 identityKeyPair
.getPublicKey(),
80 dependencies
.getAccountManager().setPreKeys(preKeyUpload
);
83 private List
<PreKeyRecord
> generatePreKeys(ServiceIdType serviceIdType
) {
84 final var offset
= account
.getPreKeyIdOffset(serviceIdType
);
86 var records
= KeyUtils
.generatePreKeyRecords(offset
, ServiceConfig
.PREKEY_BATCH_SIZE
);
87 account
.addPreKeys(serviceIdType
, records
);
92 private SignedPreKeyRecord
generateSignedPreKey(ServiceIdType serviceIdType
, IdentityKeyPair identityKeyPair
) {
93 final var signedPreKeyId
= account
.getNextSignedPreKeyId(serviceIdType
);
95 var record = KeyUtils
.generateSignedPreKeyRecord(identityKeyPair
, signedPreKeyId
);
96 account
.addSignedPreKey(serviceIdType
, record);