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
.Pair
;
6 import org
.asamk
.signal
.manager
.api
.PinLockedException
;
7 import org
.asamk
.signal
.manager
.helper
.PinHelper
;
8 import org
.whispersystems
.signalservice
.api
.KbsPinData
;
9 import org
.whispersystems
.signalservice
.api
.SignalServiceAccountManager
;
10 import org
.whispersystems
.signalservice
.api
.kbs
.MasterKey
;
11 import org
.whispersystems
.signalservice
.internal
.ServiceResponse
;
12 import org
.whispersystems
.signalservice
.internal
.push
.LockedException
;
13 import org
.whispersystems
.signalservice
.internal
.push
.RequestVerificationCodeResponse
;
14 import org
.whispersystems
.signalservice
.internal
.push
.VerifyAccountResponse
;
16 import java
.io
.IOException
;
17 import java
.util
.Optional
;
19 public class NumberVerificationUtils
{
21 public static void requestVerificationCode(
22 SignalServiceAccountManager accountManager
, String captcha
, boolean voiceVerification
23 ) throws IOException
, CaptchaRequiredException
{
24 captcha
= captcha
== null ?
null : captcha
.replace("signalcaptcha://", "");
26 final ServiceResponse
<RequestVerificationCodeResponse
> response
;
27 if (voiceVerification
) {
28 response
= accountManager
.requestVoiceVerificationCode(Utils
.getDefaultLocale(null),
29 Optional
.ofNullable(captcha
),
33 response
= accountManager
.requestSmsVerificationCode(false,
34 Optional
.ofNullable(captcha
),
39 handleResponseException(response
);
40 } catch (org
.whispersystems
.signalservice
.api
.push
.exceptions
.CaptchaRequiredException e
) {
41 throw new CaptchaRequiredException(e
.getMessage(), e
);
45 public static Pair
<VerifyAccountResponse
, MasterKey
> verifyNumber(
46 String verificationCode
, String pin
, PinHelper pinHelper
, Verifier verifier
47 ) throws IOException
, PinLockedException
, IncorrectPinException
{
48 verificationCode
= verificationCode
.replace("-", "");
50 final var response
= verifyAccountWithCode(verificationCode
, null, verifier
);
52 return new Pair
<>(response
, null);
53 } catch (LockedException e
) {
55 throw new PinLockedException(e
.getTimeRemaining());
58 KbsPinData registrationLockData
;
59 registrationLockData
= pinHelper
.getRegistrationLockData(pin
, e
);
60 if (registrationLockData
== null) {
64 var registrationLock
= registrationLockData
.getMasterKey().deriveRegistrationLock();
65 VerifyAccountResponse response
;
67 response
= verifyAccountWithCode(verificationCode
, registrationLock
, verifier
);
68 } catch (LockedException _e
) {
69 throw new AssertionError("KBS Pin appeared to matched but reg lock still failed!");
72 return new Pair
<>(response
, registrationLockData
.getMasterKey());
76 private static VerifyAccountResponse
verifyAccountWithCode(
77 final String verificationCode
, final String registrationLock
, final Verifier verifier
78 ) throws IOException
{
79 final var response
= verifier
.verify(verificationCode
, registrationLock
);
80 handleResponseException(response
);
81 return response
.getResult().get();
84 private static void handleResponseException(final ServiceResponse
<?
> response
) throws IOException
{
85 final var throwableOptional
= response
.getExecutionError().or(response
::getApplicationError
);
86 if (throwableOptional
.isPresent()) {
87 if (throwableOptional
.get() instanceof IOException
) {
88 throw (IOException
) throwableOptional
.get();
90 throw new IOException(throwableOptional
.get());
95 public interface Verifier
{
97 ServiceResponse
<VerifyAccountResponse
> verify(
98 String verificationCode
, String registrationLock