1 package org
.asamk
.signal
.manager
.helper
;
3 import org
.asamk
.signal
.manager
.api
.IncorrectPinException
;
4 import org
.asamk
.signal
.manager
.util
.PinHashing
;
5 import org
.signal
.libsignal
.protocol
.InvalidKeyException
;
6 import org
.whispersystems
.signalservice
.api
.KbsPinData
;
7 import org
.whispersystems
.signalservice
.api
.KeyBackupService
;
8 import org
.whispersystems
.signalservice
.api
.KeyBackupServicePinException
;
9 import org
.whispersystems
.signalservice
.api
.KeyBackupSystemNoDataException
;
10 import org
.whispersystems
.signalservice
.api
.kbs
.MasterKey
;
11 import org
.whispersystems
.signalservice
.internal
.contacts
.crypto
.UnauthenticatedResponseException
;
12 import org
.whispersystems
.signalservice
.internal
.contacts
.entities
.TokenResponse
;
13 import org
.whispersystems
.signalservice
.internal
.push
.LockedException
;
15 import java
.io
.IOException
;
17 public class PinHelper
{
19 private final KeyBackupService keyBackupService
;
21 public PinHelper(final KeyBackupService keyBackupService
) {
22 this.keyBackupService
= keyBackupService
;
25 public void setRegistrationLockPin(
26 String pin
, MasterKey masterKey
27 ) throws IOException
{
28 final var pinChangeSession
= keyBackupService
.newPinChangeSession();
29 final var hashedPin
= PinHashing
.hashPin(pin
, pinChangeSession
);
32 pinChangeSession
.setPin(hashedPin
, masterKey
);
33 } catch (UnauthenticatedResponseException e
) {
34 throw new IOException(e
);
36 pinChangeSession
.enableRegistrationLock(masterKey
);
39 public void removeRegistrationLockPin() throws IOException
{
40 final var pinChangeSession
= keyBackupService
.newPinChangeSession();
41 pinChangeSession
.disableRegistrationLock();
43 pinChangeSession
.removePin();
44 } catch (UnauthenticatedResponseException e
) {
45 throw new IOException(e
);
49 public KbsPinData
getRegistrationLockData(
50 String pin
, LockedException e
51 ) throws IOException
, IncorrectPinException
{
52 var basicStorageCredentials
= e
.getBasicStorageCredentials();
53 if (basicStorageCredentials
== null) {
58 return getRegistrationLockData(pin
, basicStorageCredentials
);
59 } catch (KeyBackupSystemNoDataException ex
) {
60 throw new IOException(e
);
61 } catch (KeyBackupServicePinException ex
) {
62 throw new IncorrectPinException(ex
.getTriesRemaining());
66 private KbsPinData
getRegistrationLockData(
67 String pin
, String basicStorageCredentials
68 ) throws IOException
, KeyBackupSystemNoDataException
, KeyBackupServicePinException
{
69 var tokenResponse
= keyBackupService
.getToken(basicStorageCredentials
);
70 if (tokenResponse
== null || tokenResponse
.getTries() == 0) {
71 throw new IOException("KBS Account locked, maximum pin attempts reached.");
74 var registrationLockData
= restoreMasterKey(pin
, basicStorageCredentials
, tokenResponse
);
75 if (registrationLockData
== null) {
76 throw new AssertionError("Failed to restore master key");
78 return registrationLockData
;
81 private KbsPinData
restoreMasterKey(
82 String pin
, String basicStorageCredentials
, TokenResponse tokenResponse
83 ) throws IOException
, KeyBackupSystemNoDataException
, KeyBackupServicePinException
{
84 if (pin
== null) return null;
86 if (basicStorageCredentials
== null) {
87 throw new AssertionError("Cannot restore KBS key, no storage credentials supplied");
90 var session
= keyBackupService
.newRegistrationSession(basicStorageCredentials
, tokenResponse
);
93 var hashedPin
= PinHashing
.hashPin(pin
, session
);
94 var kbsData
= session
.restorePin(hashedPin
);
95 if (kbsData
== null) {
96 throw new AssertionError("Null not expected");
99 } catch (UnauthenticatedResponseException
| InvalidKeyException e
) {
100 throw new IOException(e
);