]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java
Handle UnauthenticatedResponseException internally
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / helper / PinHelper.java
1 package org.asamk.signal.manager.helper;
2
3 import org.asamk.signal.manager.util.PinHashing;
4 import org.whispersystems.libsignal.InvalidKeyException;
5 import org.whispersystems.signalservice.api.KbsPinData;
6 import org.whispersystems.signalservice.api.KeyBackupService;
7 import org.whispersystems.signalservice.api.KeyBackupServicePinException;
8 import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
9 import org.whispersystems.signalservice.api.kbs.MasterKey;
10 import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException;
11 import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse;
12 import org.whispersystems.signalservice.internal.push.LockedException;
13
14 import java.io.IOException;
15
16 public class PinHelper {
17
18 private final KeyBackupService keyBackupService;
19
20 public PinHelper(final KeyBackupService keyBackupService) {
21 this.keyBackupService = keyBackupService;
22 }
23
24 public void setRegistrationLockPin(
25 String pin, MasterKey masterKey
26 ) throws IOException {
27 final var pinChangeSession = keyBackupService.newPinChangeSession();
28 final var hashedPin = PinHashing.hashPin(pin, pinChangeSession);
29
30 try {
31 pinChangeSession.setPin(hashedPin, masterKey);
32 } catch (UnauthenticatedResponseException e) {
33 throw new IOException(e);
34 }
35 pinChangeSession.enableRegistrationLock(masterKey);
36 }
37
38 public void removeRegistrationLockPin() throws IOException {
39 final var pinChangeSession = keyBackupService.newPinChangeSession();
40 pinChangeSession.disableRegistrationLock();
41 try {
42 pinChangeSession.removePin();
43 } catch (UnauthenticatedResponseException e) {
44 throw new IOException(e);
45 }
46 }
47
48 public KbsPinData getRegistrationLockData(
49 String pin, LockedException e
50 ) throws IOException, KeyBackupSystemNoDataException, KeyBackupServicePinException {
51 var basicStorageCredentials = e.getBasicStorageCredentials();
52 if (basicStorageCredentials == null) {
53 return null;
54 }
55
56 return getRegistrationLockData(pin, basicStorageCredentials);
57 }
58
59 private KbsPinData getRegistrationLockData(
60 String pin, String basicStorageCredentials
61 ) throws IOException, KeyBackupSystemNoDataException, KeyBackupServicePinException {
62 var tokenResponse = keyBackupService.getToken(basicStorageCredentials);
63 if (tokenResponse == null || tokenResponse.getTries() == 0) {
64 throw new IOException("KBS Account locked, maximum pin attempts reached.");
65 }
66
67 var registrationLockData = restoreMasterKey(pin, basicStorageCredentials, tokenResponse);
68 if (registrationLockData == null) {
69 throw new AssertionError("Failed to restore master key");
70 }
71 return registrationLockData;
72 }
73
74 private KbsPinData restoreMasterKey(
75 String pin, String basicStorageCredentials, TokenResponse tokenResponse
76 ) throws IOException, KeyBackupSystemNoDataException, KeyBackupServicePinException {
77 if (pin == null) return null;
78
79 if (basicStorageCredentials == null) {
80 throw new AssertionError("Cannot restore KBS key, no storage credentials supplied");
81 }
82
83 var session = keyBackupService.newRegistrationSession(basicStorageCredentials, tokenResponse);
84
85 try {
86 var hashedPin = PinHashing.hashPin(pin, session);
87 var kbsData = session.restorePin(hashedPin);
88 if (kbsData == null) {
89 throw new AssertionError("Null not expected");
90 }
91 return kbsData;
92 } catch (UnauthenticatedResponseException | InvalidKeyException e) {
93 throw new IOException(e);
94 }
95 }
96 }