1 package org
.asamk
.signal
.manager
.helper
;
3 import org
.asamk
.signal
.manager
.api
.IncorrectPinException
;
4 import org
.slf4j
.Logger
;
5 import org
.slf4j
.LoggerFactory
;
6 import org
.whispersystems
.signalservice
.api
.KeyBackupService
;
7 import org
.whispersystems
.signalservice
.api
.kbs
.MasterKey
;
8 import org
.whispersystems
.signalservice
.api
.kbs
.PinHashUtil
;
9 import org
.whispersystems
.signalservice
.api
.svr
.SecureValueRecovery
;
10 import org
.whispersystems
.signalservice
.api
.svr
.SecureValueRecoveryV1
;
11 import org
.whispersystems
.signalservice
.api
.svr
.SecureValueRecoveryV2
;
12 import org
.whispersystems
.signalservice
.internal
.contacts
.crypto
.UnauthenticatedResponseException
;
13 import org
.whispersystems
.signalservice
.internal
.push
.AuthCredentials
;
14 import org
.whispersystems
.signalservice
.internal
.push
.LockedException
;
16 import java
.io
.IOException
;
17 import java
.util
.Collection
;
19 public class PinHelper
{
21 private final static Logger logger
= LoggerFactory
.getLogger(PinHelper
.class);
23 private final KeyBackupService keyBackupService
;
24 private final SecureValueRecoveryV1 secureValueRecoveryV1
;
25 private final SecureValueRecoveryV2 secureValueRecoveryV2
;
26 private final Collection
<KeyBackupService
> fallbackKeyBackupServices
;
29 final KeyBackupService keyBackupService
,
30 final Collection
<KeyBackupService
> fallbackKeyBackupServices
,
31 SecureValueRecoveryV2 secureValueRecoveryV2
33 this.keyBackupService
= keyBackupService
;
34 this.fallbackKeyBackupServices
= fallbackKeyBackupServices
;
35 this.secureValueRecoveryV1
= new SecureValueRecoveryV1(keyBackupService
);
36 this.secureValueRecoveryV2
= secureValueRecoveryV2
;
39 public void setRegistrationLockPin(
40 String pin
, MasterKey masterKey
41 ) throws IOException
{
42 final var pinChangeSession
= keyBackupService
.newPinChangeSession();
43 final var hashedPin
= PinHashUtil
.hashPin(pin
, pinChangeSession
.hashSalt());
46 pinChangeSession
.setPin(hashedPin
, masterKey
);
47 } catch (UnauthenticatedResponseException e
) {
48 throw new IOException(e
);
50 pinChangeSession
.enableRegistrationLock(masterKey
);
52 final var backupResponse
= secureValueRecoveryV2
.setPin(pin
, masterKey
).execute();
53 if (backupResponse
instanceof SecureValueRecovery
.BackupResponse
.Success
) {
54 } else if (backupResponse
instanceof SecureValueRecovery
.BackupResponse
.ServerRejected
) {
55 logger
.warn("Backup svr2 failed: ServerRejected");
56 } else if (backupResponse
instanceof SecureValueRecovery
.BackupResponse
.EnclaveNotFound
) {
57 logger
.warn("Backup svr2 failed: EnclaveNotFound");
58 } else if (backupResponse
instanceof SecureValueRecovery
.BackupResponse
.ExposeFailure
) {
59 logger
.warn("Backup svr2 failed: ExposeFailure");
60 } else if (backupResponse
instanceof SecureValueRecovery
.BackupResponse
.ApplicationError error
) {
61 throw new IOException(error
.getException());
62 } else if (backupResponse
instanceof SecureValueRecovery
.BackupResponse
.NetworkError error
) {
63 throw error
.getException();
65 throw new AssertionError("Unexpected response");
69 public void migrateRegistrationLockPin(String pin
, MasterKey masterKey
) throws IOException
{
70 setRegistrationLockPin(pin
, masterKey
);
72 for (final var keyBackupService
: fallbackKeyBackupServices
) {
74 final var pinChangeSession
= keyBackupService
.newPinChangeSession();
75 pinChangeSession
.removePin();
76 } catch (Exception e
) {
77 logger
.warn("Failed to remove PIN from fallback KBS: {}", e
.getMessage());
82 public void removeRegistrationLockPin() throws IOException
{
83 final var pinChangeSession
= keyBackupService
.newPinChangeSession();
84 pinChangeSession
.disableRegistrationLock();
86 pinChangeSession
.removePin();
87 } catch (UnauthenticatedResponseException e
) {
88 throw new IOException(e
);
91 final var deleteResponse
= secureValueRecoveryV2
.deleteData();
92 if (deleteResponse
instanceof SecureValueRecovery
.DeleteResponse
.Success
) {
93 } else if (deleteResponse
instanceof SecureValueRecovery
.DeleteResponse
.ServerRejected
) {
94 logger
.warn("Delete svr2 failed: ServerRejected");
95 } else if (deleteResponse
instanceof SecureValueRecovery
.DeleteResponse
.EnclaveNotFound
) {
96 logger
.warn("Delete svr2 failed: EnclaveNotFound");
97 } else if (deleteResponse
instanceof SecureValueRecovery
.DeleteResponse
.ApplicationError error
) {
98 throw new IOException(error
.getException());
99 } else if (deleteResponse
instanceof SecureValueRecovery
.DeleteResponse
.NetworkError error
) {
100 throw error
.getException();
102 throw new AssertionError("Unexpected response");
106 public SecureValueRecovery
.RestoreResponse
.Success
getRegistrationLockData(
107 String pin
, LockedException e
108 ) throws IOException
, IncorrectPinException
{
109 var svr1Credentials
= e
.getSvr1Credentials();
110 if (svr1Credentials
!= null) {
111 return getRegistrationLockData(secureValueRecoveryV1
, svr1Credentials
, pin
);
114 var svr2Credentials
= e
.getSvr2Credentials();
115 if (svr2Credentials
!= null) {
116 return getRegistrationLockData(secureValueRecoveryV2
, svr2Credentials
, pin
);
122 public SecureValueRecovery
.RestoreResponse
.Success
getRegistrationLockData(
123 SecureValueRecovery secureValueRecovery
, AuthCredentials authCredentials
, String pin
124 ) throws IOException
, IncorrectPinException
{
125 final var restoreResponse
= secureValueRecovery
.restoreDataPreRegistration(authCredentials
, pin
);
127 if (restoreResponse
instanceof SecureValueRecovery
.RestoreResponse
.Success s
) {
129 } else if (restoreResponse
instanceof SecureValueRecovery
.RestoreResponse
.PinMismatch pinMismatch
) {
130 throw new IncorrectPinException(pinMismatch
.getTriesRemaining());
131 } else if (restoreResponse
instanceof SecureValueRecovery
.RestoreResponse
.ApplicationError error
) {
132 throw new IOException(error
.getException());
133 } else if (restoreResponse
instanceof SecureValueRecovery
.RestoreResponse
.NetworkError error
) {
134 throw error
.getException();
136 throw new AssertionError("Unexpected response");