1 package org
.asamk
.signal
.manager
.util
;
3 import org
.asamk
.signal
.manager
.api
.CaptchaRequiredException
;
4 import org
.asamk
.signal
.manager
.api
.IncorrectPinException
;
5 import org
.asamk
.signal
.manager
.api
.NonNormalizedPhoneNumberException
;
6 import org
.asamk
.signal
.manager
.api
.Pair
;
7 import org
.asamk
.signal
.manager
.api
.PinLockedException
;
8 import org
.asamk
.signal
.manager
.helper
.PinHelper
;
9 import org
.whispersystems
.signalservice
.api
.KbsPinData
;
10 import org
.whispersystems
.signalservice
.api
.SignalServiceAccountManager
;
11 import org
.whispersystems
.signalservice
.api
.kbs
.MasterKey
;
12 import org
.whispersystems
.signalservice
.internal
.ServiceResponse
;
13 import org
.whispersystems
.signalservice
.internal
.push
.LockedException
;
14 import org
.whispersystems
.signalservice
.internal
.push
.RequestVerificationCodeResponse
;
15 import org
.whispersystems
.signalservice
.internal
.push
.VerifyAccountResponse
;
17 import java
.io
.IOException
;
18 import java
.util
.Locale
;
19 import java
.util
.Optional
;
21 public class NumberVerificationUtils
{
23 public static void requestVerificationCode(
24 SignalServiceAccountManager accountManager
, String captcha
, boolean voiceVerification
25 ) throws IOException
, CaptchaRequiredException
, NonNormalizedPhoneNumberException
{
26 captcha
= captcha
== null ?
null : captcha
.replace("signalcaptcha://", "");
27 final ServiceResponse
<RequestVerificationCodeResponse
> response
;
28 final var locale
= Utils
.getDefaultLocale(Locale
.US
);
29 if (voiceVerification
) {
30 response
= accountManager
.requestVoiceVerificationCode(locale
,
31 Optional
.ofNullable(captcha
),
35 response
= accountManager
.requestSmsVerificationCode(locale
,
37 Optional
.ofNullable(captcha
),
42 handleResponseException(response
);
43 } catch (org
.whispersystems
.signalservice
.api
.push
.exceptions
.CaptchaRequiredException e
) {
44 throw new CaptchaRequiredException(e
.getMessage(), e
);
45 } catch (org
.whispersystems
.signalservice
.api
.push
.exceptions
.NonNormalizedPhoneNumberException e
) {
46 throw new NonNormalizedPhoneNumberException("Phone number is not normalized ("
48 + "). Expected normalized: "
49 + e
.getNormalizedNumber(), e
);
53 public static Pair
<VerifyAccountResponse
, MasterKey
> verifyNumber(
54 String verificationCode
, String pin
, PinHelper pinHelper
, Verifier verifier
55 ) throws IOException
, PinLockedException
, IncorrectPinException
{
56 verificationCode
= verificationCode
.replace("-", "");
58 final var response
= verifyAccountWithCode(verificationCode
, null, verifier
);
60 return new Pair
<>(response
, null);
61 } catch (LockedException e
) {
63 throw new PinLockedException(e
.getTimeRemaining());
66 KbsPinData registrationLockData
;
67 registrationLockData
= pinHelper
.getRegistrationLockData(pin
, e
);
68 if (registrationLockData
== null) {
72 var registrationLock
= registrationLockData
.getMasterKey().deriveRegistrationLock();
73 VerifyAccountResponse response
;
75 response
= verifyAccountWithCode(verificationCode
, registrationLock
, verifier
);
76 } catch (LockedException _e
) {
77 throw new AssertionError("KBS Pin appeared to matched but reg lock still failed!");
80 return new Pair
<>(response
, registrationLockData
.getMasterKey());
84 private static VerifyAccountResponse
verifyAccountWithCode(
85 final String verificationCode
, final String registrationLock
, final Verifier verifier
86 ) throws IOException
{
87 final var response
= verifier
.verify(verificationCode
, registrationLock
);
88 handleResponseException(response
);
89 return response
.getResult().get();
92 private static void handleResponseException(final ServiceResponse
<?
> response
) throws IOException
{
93 final var throwableOptional
= response
.getExecutionError().or(response
::getApplicationError
);
94 if (throwableOptional
.isPresent()) {
95 if (throwableOptional
.get() instanceof IOException
) {
96 throw (IOException
) throwableOptional
.get();
98 throw new IOException(throwableOptional
.get());
103 public interface Verifier
{
105 ServiceResponse
<VerifyAccountResponse
> verify(
106 String verificationCode
, String registrationLock