예제 #1
0
        public NewDeviceLinkResult FinishNewDeviceRegistration(IdentityKeyPair tempIdentity, string signalingKey, string password, bool sms, bool fetches, int regid, string name)
        {
            ProvisionMessage pm = ProvisioningSocket.GetProvisioningMessage(tempIdentity);
            string           provisioningCode = pm.ProvisioningCode;

            byte[] publicKeyBytes = pm.IdentityKeyPublic.ToByteArray();
            if (publicKeyBytes.Length == 32)
            {
                byte[] type = { Curve.DJB_TYPE };
                publicKeyBytes = ByteUtil.combine(type, publicKeyBytes);
            }
            ECPublicKey publicKey = Curve.decodePoint(publicKeyBytes, 0);

            byte[]          privateKeyBytes = pm.IdentityKeyPrivate.ToByteArray();
            ECPrivateKey    privateKey      = Curve.decodePrivatePoint(privateKeyBytes);
            IdentityKeyPair identity        = new IdentityKeyPair(new IdentityKey(publicKey), privateKey);

            pushServiceSocket = new PushServiceSocket(Urls, new StaticCredentialsProvider(pm.Number, password, null, -1), userAgent);
            int deviceId = pushServiceSocket.finishNewDeviceRegistration(provisioningCode, signalingKey, sms, fetches, regid, name);

            return(new NewDeviceLinkResult()
            {
                DeviceId = deviceId,
                Identity = identity,
                Number = pm.Number
            });
        }
예제 #2
0
        private async Task HandleMismatchedDevices(CancellationToken token, PushServiceSocket socket, SignalServiceAddress recipient, MismatchedDevices mismatchedDevices)
        {
            try
            {
                foreach (uint extraDeviceId in mismatchedDevices.ExtraDevices)
                {
                    store.DeleteSession(new SignalProtocolAddress(recipient.E164number, extraDeviceId));
                }

                foreach (uint missingDeviceId in mismatchedDevices.MissingDevices)
                {
                    PreKeyBundle preKey = await socket.GetPreKey(token, recipient, missingDeviceId);

                    try
                    {
                        SessionBuilder sessionBuilder = new SessionBuilder(store, new SignalProtocolAddress(recipient.E164number, missingDeviceId));
                        sessionBuilder.process(preKey);
                    }
                    catch (libsignal.exceptions.UntrustedIdentityException)
                    {
                        throw new UntrustedIdentityException("Untrusted identity key!", recipient.E164number, preKey.getIdentityKey());
                    }
                }
            }
            catch (InvalidKeyException e)
            {
                throw new Exception(e.Message);
            }
        }
예제 #3
0
        private async Task <OutgoingPushMessageList> GetEncryptedMessages(CancellationToken token,
                                                                          PushServiceSocket socket,
                                                                          SignalServiceAddress recipient,
                                                                          long timestamp,
                                                                          byte[] plaintext,
                                                                          bool silent)
        {
            List <OutgoingPushMessage> messages = new List <OutgoingPushMessage>();

            bool myself = recipient.Equals(localAddress);

            if (!myself || CredentialsProvider.DeviceId != SignalServiceAddress.DEFAULT_DEVICE_ID)
            {
                messages.Add(await GetEncryptedMessage(token, socket, recipient, SignalServiceAddress.DEFAULT_DEVICE_ID, plaintext, silent));
            }

            foreach (uint deviceId in store.GetSubDeviceSessions(recipient.E164number))
            {
                if (!myself || deviceId != CredentialsProvider.DeviceId)
                {
                    if (store.ContainsSession(new SignalProtocolAddress(recipient.E164number, deviceId)))
                    {
                        messages.Add(await GetEncryptedMessage(token, socket, recipient, deviceId, plaintext, silent));
                    }
                }
            }

            return(new OutgoingPushMessageList(recipient.E164number, (ulong)timestamp, recipient.Relay, messages));
        }
 /// <summary>
 /// Construct a SignalServivceAccountManager.
 /// </summary>
 /// <param name="urls">The URL for the Signal Service.</param>
 /// <param name="user">A Signal Service phone number</param>
 /// <param name="password">A Signal Service password.</param>
 /// <param name="userAgent">A string which identifies the client software.</param>
 public SignalServiceAccountManager(SignalServiceUrl[] urls,
                                    string user, string password, string userAgent)
 {
     this.pushServiceSocket = new PushServiceSocket(urls, new StaticCredentialsProvider(user, password, null), userAgent);
     this.user      = user;
     this.userAgent = userAgent;
 }
예제 #5
0
        private void handleMismatchedDevices(PushServiceSocket socket, SignalServiceAddress recipient, MismatchedDevices mismatchedDevices)
        {
            try
            {
                foreach (uint extraDeviceId in mismatchedDevices.getExtraDevices())
                {
                    store.DeleteSession(new SignalProtocolAddress(recipient.getNumber(), extraDeviceId));
                }

                foreach (uint missingDeviceId in mismatchedDevices.getMissingDevices())
                {
                    PreKeyBundle preKey = socket.getPreKey(recipient, missingDeviceId);

                    try
                    {
                        SessionBuilder sessionBuilder = new SessionBuilder(store, new SignalProtocolAddress(recipient.getNumber(), missingDeviceId));
                        sessionBuilder.process(preKey);
                    }
                    catch (libsignal.exceptions.UntrustedIdentityException e)
                    {
                        throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey());
                    }
                }
            }
            catch (InvalidKeyException e)
            {
                throw new Exception(e.Message);
            }
        }
예제 #6
0
        private OutgoingPushMessageList getEncryptedMessages(PushServiceSocket socket,
                                                             SignalServiceAddress recipient,
                                                             long timestamp,
                                                             byte[] plaintext,
                                                             bool legacy,
                                                             bool silent)
        {
            List <OutgoingPushMessage> messages = new List <OutgoingPushMessage>();

            bool myself = recipient.Equals(localAddress);

            if (!myself || CredentialsProvider.GetDeviceId() != SignalServiceAddress.DEFAULT_DEVICE_ID)
            {
                messages.Add(getEncryptedMessage(socket, recipient, SignalServiceAddress.DEFAULT_DEVICE_ID, plaintext, legacy, silent));
            }

            foreach (uint deviceId in store.GetSubDeviceSessions(recipient.getNumber()))
            {
                if (!myself || deviceId != CredentialsProvider.GetDeviceId())
                {
                    messages.Add(getEncryptedMessage(socket, recipient, deviceId, plaintext, legacy, silent));
                }
            }

            return(new OutgoingPushMessageList(recipient.getNumber(), (ulong)timestamp, recipient.getRelay().HasValue ? recipient.getRelay().ForceGetValue() : null, messages));
        }
예제 #7
0
 /**
  * Construct a TextSecureAccountManager.
  *
  * @param url The URL for the TextSecure server.
  * @param trustStore The {@link org.whispersystems.textsecure.api.push.TrustStore} for the TextSecure server's TLS certificate.
  * @param user A TextSecure phone number.
  * @param password A TextSecure password.
  */
 public TextSecureAccountManager(String url, TrustStore trustStore,
                                 String user, String password, string userAgent)
 {
     this.pushServiceSocket = new PushServiceSocket(url, trustStore, new StaticCredentialsProvider(user, password, null), userAgent);
     this.user      = user;
     this.userAgent = userAgent;
 }
 /// <summary>
 /// Construct a SignalServiceMessageReceiver.
 /// </summary>
 /// <param name="urls">The URL of the Signal Service.</param>
 /// <param name="credentials">The Signal Service user's credentials</param>
 /// <param name="userAgent"></param>
 public SignalServiceMessageReceiver(SignalServiceConfiguration urls, ICredentialsProvider credentials, string userAgent, HttpClient httpClient)
 {
     Urls = urls;
     CredentialsProvider = credentials;
     Socket    = new PushServiceSocket(urls, credentials, userAgent, httpClient);
     UserAgent = userAgent;
 }
예제 #9
0
 /// <summary>
 /// Construct a SignalServivceAccountManager
 /// </summary>
 /// <param name="configuration">The URL configuration for the Signal Service</param>
 /// <param name="user">A Signal Service phone number</param>
 /// <param name="password">A Signal Service password</param>
 /// <param name="deviceId">A Signal Service device id</param>
 /// <param name="userAgent">A string which identifies the client software</param>
 public SignalServiceAccountManager(SignalServiceConfiguration configuration,
                                    string user, string password, int deviceId, string userAgent)
 {
     PushServiceSocket = new PushServiceSocket(configuration, new StaticCredentialsProvider(user, password, null, deviceId), userAgent);
     User      = user;
     UserAgent = userAgent;
 }
 /// <summary>
 /// Construct a SignalServiceMessageReceiver.
 /// </summary>
 /// <param name="urls">The URL of the Signal Service.</param>
 /// <param name="credentials">The Signal Service user's credentials</param>
 /// <param name="userAgent"></param>
 public SignalServiceMessageReceiver(SignalServiceUrl[] urls, CredentialsProvider credentials, string userAgent)
 {
     this.urls = urls;
     this.credentialsProvider = credentials;
     this.socket    = new PushServiceSocket(urls, credentials, userAgent);
     this.userAgent = userAgent;
 }
예제 #11
0
 /// <summary>
 /// Construct a SignalServiceAccountManager for linking as a slave device
 /// </summary>
 /// <param name="configuration">The URL configuration for the Signal Service</param>
 /// <param name="userAgent">A string which identifies the client software</param>
 /// <param name="webSocketFactory">A factory which creates websocket connection objects</param>
 public SignalServiceAccountManager(SignalServiceConfiguration configuration, string userAgent, HttpClient httpClient, ISignalWebSocketFactory webSocketFactory)
 {
     this.httpClient    = httpClient;
     this.configuration = configuration;
     this.userAgent     = userAgent;
     credentials        = new StaticCredentialsProvider(null, null, null, (int)SignalServiceAddress.DEFAULT_DEVICE_ID);
     pushServiceSocket  = new PushServiceSocket(configuration, credentials, userAgent, httpClient);
 }
예제 #12
0
 /**
  * Construct a TextSecureMessageReceiver.
  *
  * @param url The URL of the TextSecure server.
  * @param trustStore The {@link org.whispersystems.textsecure.api.push.TrustStore} containing
  *                   the server's TLS signing certificate.
  * @param credentials The TextSecure user's credentials.
  */
 public TextSecureMessageReceiver(String url, TrustStore trustStore, CredentialsProvider credentials, string userAgent)
 {
     this.url                 = url;
     this.trustStore          = trustStore;
     this.credentialsProvider = credentials;
     this.socket              = new PushServiceSocket(url, trustStore, credentials, userAgent);
     this.userAgent           = userAgent;
 }
 /**
  * Construct a TextSecureMessageSender.
  *
  * @param url The URL of the TextSecure server.
  * @param trustStore The trust store containing the TextSecure server's signing TLS certificate.
  * @param user The TextSecure username (eg phone number).
  * @param password The TextSecure user's password.
  * @param store The AxolotlStore.
  * @param eventListener An optional event listener, which fires whenever sessions are
  *                      setup or torn down for a recipient.
  */
 public TextSecureMessageSender(String url, TrustStore trustStore,
                                String user, String password,
                                AxolotlStore store,
                                May <EventListener> eventListener, String userAgent)
 {
     this.socket        = new PushServiceSocket(url, trustStore, new StaticCredentialsProvider(user, password, null), userAgent);
     this.store         = store;
     this.localAddress  = new TextSecureAddress(user);
     this.eventListener = eventListener;
 }
 public SignalServiceAccountManager(SignalServiceConfiguration configuration,
                                    ICredentialsProvider credentialsProvider,
                                    string signalAgent,
                                    HttpClient httpClient)
 {
     this.pushServiceSocket = new PushServiceSocket(configuration, credentialsProvider, signalAgent, httpClient);
     this.configuration     = configuration;
     this.credentials       = credentialsProvider;
     this.userAgent         = signalAgent;
     this.httpClient        = httpClient;
 }
        private async Task <OutgoingPushMessage> GetEncryptedMessage(CancellationToken token,
                                                                     PushServiceSocket socket,
                                                                     SignalServiceAddress recipient,
                                                                     UnidentifiedAccess?unidentifiedAccess,
                                                                     uint deviceId,
                                                                     byte[] plaintext)
        {
            SignalProtocolAddress signalProtocolAddress = new SignalProtocolAddress(recipient.E164number, deviceId);
            SignalServiceCipher   cipher = new SignalServiceCipher(LocalAddress, Store, null);

            if (!Store.ContainsSession(signalProtocolAddress))
            {
                try
                {
                    List <PreKeyBundle> preKeys = await socket.GetPreKeys(token, recipient, unidentifiedAccess, deviceId);

                    foreach (PreKeyBundle preKey in preKeys)
                    {
                        if (CredentialsProvider.User.Equals(recipient.E164number) && CredentialsProvider.DeviceId == preKey.getDeviceId())
                        {
                            continue;
                        }
                        try
                        {
                            SignalProtocolAddress preKeyAddress  = new SignalProtocolAddress(recipient.E164number, preKey.getDeviceId());
                            SessionBuilder        sessionBuilder = new SessionBuilder(Store, preKeyAddress);
                            sessionBuilder.process(preKey);
                        }
                        catch (libsignal.exceptions.UntrustedIdentityException)
                        {
                            throw new UntrustedIdentityException("Untrusted identity key!", recipient.E164number, preKey.getIdentityKey());
                        }
                    }

                    if (EventListener != null)
                    {
                        EventListener.OnSecurityEvent(recipient);
                    }
                }
                catch (InvalidKeyException e)
                {
                    throw new Exception(e.Message);
                }
            }

            try
            {
                return(cipher.Encrypt(signalProtocolAddress, unidentifiedAccess, plaintext));
            }
            catch (libsignal.exceptions.UntrustedIdentityException e)
            {
                throw new UntrustedIdentityException("Untrusted on send", e.getName(), e.getUntrustedIdentity());
            }
        }
        /// <summary>
        /// Finishes a registration as a new device.
        /// Called by the new device. This method blocks until the already verified device has verified this device.
        /// </summary>
        /// <param name="token"></param>
        /// <param name="provisionMessage"></param>
        /// <param name="signalingKey"></param>
        /// <param name="password"></param>
        /// <param name="sms"></param>
        /// <param name="fetches"></param>
        /// <param name="regid"></param>
        /// <param name="name"></param>
        /// <returns>Device id</returns>
        public async Task <int> FinishNewDeviceRegistration(CancellationToken token, SignalServiceProvisionMessage provisionMessage, string signalingKey, string password, bool sms, bool fetches, int regid, string name)
        {
            pushServiceSocket = new PushServiceSocket(configuration, new StaticCredentialsProvider(provisionMessage.Number, password, null, -1), userAgent, httpClient);

            // update credentials and pushServiceSocket to keep internal state consistent
            int deviceId = await pushServiceSocket.FinishNewDeviceRegistration(token, provisionMessage.Code, signalingKey, sms, fetches, regid, name);

            credentials       = new StaticCredentialsProvider(provisionMessage.Number, password, null, deviceId);
            pushServiceSocket = new PushServiceSocket(configuration, credentials, userAgent, httpClient);
            return(deviceId);
        }
예제 #17
0
 /// <summary>
 /// Construct a SignalServiceMessageSender
 /// </summary>
 /// <param name="urls">The URL of the Signal Service.</param>
 /// <param name="user">The Signal Service username (eg phone number).</param>
 /// <param name="password">The Signal Service user password</param>
 /// <param name="store">The SignalProtocolStore.</param>
 /// <param name="eventListener">An optional event listener, which fires whenever sessions are
 /// setup or torn down for a recipient.</param>
 /// <param name="userAgent"></param>
 public SignalServiceMessageSender(SignalServiceUrl[] urls,
                                   string user, string password,
                                   SignalProtocolStore store,
                                   May <SignalServiceMessagePipe> pipe,
                                   May <EventListener> eventListener, string userAgent)
 {
     this.socket        = new PushServiceSocket(urls, new StaticCredentialsProvider(user, password, null), userAgent);
     this.store         = store;
     this.localAddress  = new SignalServiceAddress(user);
     this.pipe          = pipe;
     this.eventListener = eventListener;
 }
예제 #18
0
 /// <summary>
 /// Construct a SignalServiceMessageSender
 /// </summary>
 /// <param name="token">A CancellationToken to cancel the sender's operations</param>
 /// <param name="urls">The URL of the Signal Service.</param>
 /// <param name="user">The Signal Service username (eg phone number).</param>
 /// <param name="password">The Signal Service user password</param>
 /// <param name="deviceId">Tbe Signal Service device id</param>
 /// <param name="store">The SignalProtocolStore.</param>
 /// <param name="pipe">An optional SignalServiceMessagePipe</param>
 /// <param name="eventListener">An optional event listener, which fires whenever sessions are
 /// setup or torn down for a recipient.</param>
 /// <param name="userAgent"></param>
 public SignalServiceMessageSender(CancellationToken token, SignalServiceConfiguration urls,
                                   string user, string password, int deviceId,
                                   SignalProtocolStore store,
                                   SignalServiceMessagePipe pipe,
                                   IEventListener eventListener, string userAgent)
 {
     Token = token;
     CredentialsProvider = new StaticCredentialsProvider(user, password, null, deviceId);
     this.socket         = new PushServiceSocket(urls, CredentialsProvider, userAgent);
     this.store          = store;
     this.localAddress   = new SignalServiceAddress(user);
     this.pipe           = pipe;
     this.eventListener  = eventListener;
 }
 /// <summary>
 /// Construct a SignalServiceMessageSender
 /// </summary>
 /// <param name="token">A CancellationToken to cancel the sender's operations</param>
 /// <param name="urls">The URL of the Signal Service.</param>
 /// <param name="user">The Signal Service username (eg phone number).</param>
 /// <param name="password">The Signal Service user password</param>
 /// <param name="deviceId">Tbe Signal Service device id</param>
 /// <param name="store">The SignalProtocolStore.</param>
 /// <param name="pipe">An optional SignalServiceMessagePipe</param>
 /// <param name="unidentifiedPipe"></param>
 /// <param name="eventListener">An optional event listener, which fires whenever sessions are
 /// setup or torn down for a recipient.</param>
 /// <param name="userAgent"></param>
 /// <param name="isMultiDevice"></param>
 public SignalServiceMessageSender(CancellationToken token, SignalServiceConfiguration urls,
                                   string user, string password, int deviceId,
                                   SignalProtocolStore store,
                                   string userAgent,
                                   bool isMultiDevice,
                                   SignalServiceMessagePipe?pipe,
                                   SignalServiceMessagePipe?unidentifiedPipe,
                                   IEventListener eventListener)
 {
     Token = token;
     CredentialsProvider = new StaticCredentialsProvider(user, password, null, deviceId);
     Socket           = new PushServiceSocket(urls, CredentialsProvider, userAgent);
     Store            = store;
     LocalAddress     = new SignalServiceAddress(user);
     Pipe             = pipe;
     UnidentifiedPipe = unidentifiedPipe;
     IsMultiDevice    = isMultiDevice;
     EventListener    = eventListener;
 }
예제 #20
0
        private OutgoingPushMessage getEncryptedMessage(PushServiceSocket socket, SignalServiceAddress recipient, uint deviceId, byte[] plaintext, bool legacy, bool silent)
        {
            SignalProtocolAddress signalProtocolAddress = new SignalProtocolAddress(recipient.getNumber(), deviceId);
            SignalServiceCipher   cipher = new SignalServiceCipher(localAddress, store);

            if (!store.ContainsSession(signalProtocolAddress))
            {
                try
                {
                    List <PreKeyBundle> preKeys = socket.getPreKeys(recipient, deviceId);

                    foreach (PreKeyBundle preKey in preKeys)
                    {
                        if (CredentialsProvider.GetUser().Equals(recipient.getNumber()) && CredentialsProvider.GetDeviceId() == preKey.getDeviceId())
                        {
                            continue;
                        }
                        try
                        {
                            SignalProtocolAddress preKeyAddress  = new SignalProtocolAddress(recipient.getNumber(), preKey.getDeviceId());
                            SessionBuilder        sessionBuilder = new SessionBuilder(store, preKeyAddress);
                            sessionBuilder.process(preKey);
                        }
                        catch (libsignal.exceptions.UntrustedIdentityException e)
                        {
                            throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey());
                        }
                    }

                    if (eventListener != null)
                    {
                        eventListener.onSecurityEvent(recipient);
                    }
                }
                catch (InvalidKeyException e)
                {
                    throw new Exception(e.Message);
                }
            }

            return(cipher.encrypt(signalProtocolAddress, plaintext, legacy, silent));
        }
        private async Task <OutgoingPushMessageList> getEncryptedMessages(PushServiceSocket socket,
                                                                          TextSecureAddress recipient,
                                                                          ulong timestamp,
                                                                          byte[] plaintext,
                                                                          bool legacy)
        {
            List <OutgoingPushMessage> messages = new List <OutgoingPushMessage>();

            if (!recipient.Equals(localAddress))
            {
                messages.Add(await getEncryptedMessage(socket, recipient, TextSecureAddress.DEFAULT_DEVICE_ID, plaintext, legacy));
            }

            foreach (uint deviceId in store.GetSubDeviceSessions(recipient.getNumber()))
            {
                messages.Add(await getEncryptedMessage(socket, recipient, deviceId, plaintext, legacy));
            }

            return(new OutgoingPushMessageList(recipient.getNumber(), timestamp, recipient.getRelay().HasValue ? recipient.getRelay().ForceGetValue() : null, messages));
        }
        private async Task <OutgoingPushMessage> getEncryptedMessage(PushServiceSocket socket, TextSecureAddress recipient, uint deviceId, byte[] plaintext, bool legacy)
        {
            AxolotlAddress   axolotlAddress = new AxolotlAddress(recipient.getNumber(), deviceId);
            TextSecureCipher cipher         = new TextSecureCipher(localAddress, store);

            if (!store.ContainsSession(axolotlAddress))
            {
                try
                {
                    List <PreKeyBundle> preKeys = await socket.getPreKeys(recipient, deviceId);

                    foreach (PreKeyBundle preKey in preKeys)
                    {
                        try
                        {
                            AxolotlAddress preKeyAddress  = new AxolotlAddress(recipient.getNumber(), preKey.getDeviceId());
                            SessionBuilder sessionBuilder = new SessionBuilder(store, preKeyAddress);
                            sessionBuilder.process(preKey);
                        }
                        catch (libaxolotl.exceptions.UntrustedIdentityException e)
                        {
                            throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey());
                        }
                    }

                    if (eventListener.HasValue)
                    {
                        eventListener.ForceGetValue().onSecurityEvent(recipient);
                    }
                }
                catch (InvalidKeyException e)
                {
                    throw new Exception(e.Message);
                }
            }

            return(cipher.encrypt(axolotlAddress, plaintext, legacy));
        }
예제 #23
0
 public SignalServiceAccountManager(SignalServiceUrl[] urls, CancellationToken token, string userAgent)
 {
     Urls = urls;
     ProvisioningSocket = new ProvisioningSocket(urls[0].getUrl(), token);
     pushServiceSocket  = new PushServiceSocket(urls, new StaticCredentialsProvider(null, null, null, (int)SignalServiceAddress.DEFAULT_DEVICE_ID), userAgent);
 }
예제 #24
0
 /// <summary>
 /// Finishes a registration as a new device.
 /// Called by the new device. This method blocks until the already verified device has verified this device.
 /// </summary>
 /// <param name="token"></param>
 /// <param name="provisionMessage"></param>
 /// <param name="signalingKey"></param>
 /// <param name="password"></param>
 /// <param name="sms"></param>
 /// <param name="fetches"></param>
 /// <param name="regid"></param>
 /// <param name="name"></param>
 /// <returns></returns>
 public async Task <int> FinishNewDeviceRegistration(CancellationToken token, SignalServiceProvisionMessage provisionMessage, string signalingKey, string password, bool sms, bool fetches, int regid, string name)
 {
     PushServiceSocket = new PushServiceSocket(Configuration, new StaticCredentialsProvider(provisionMessage.Number, password, null, -1), UserAgent);
     return(await PushServiceSocket.FinishNewDeviceRegistration(token, provisionMessage.Code, signalingKey, sms, fetches, regid, name));
 }
예제 #25
0
 /// <summary>
 /// Construct a SignalServiceAccountManager for linking as a slave device
 /// </summary>
 /// <param name="configuration">The URL configuration for the Signal Service</param>
 /// <param name="userAgent">A string which identifies the client software</param>
 /// <param name="webSocketFactory">A factory which creates websocket connection objects</param>
 public SignalServiceAccountManager(SignalServiceConfiguration configuration, string userAgent, ISignalWebSocketFactory webSocketFactory)
 {
     Configuration     = configuration;
     UserAgent         = userAgent;
     PushServiceSocket = new PushServiceSocket(configuration, new StaticCredentialsProvider(null, null, null, (int)SignalServiceAddress.DEFAULT_DEVICE_ID), userAgent);
 }