private static SignalProtocolAddress GetPreferredProtocolAddress(SignalProtocolStore store, SignalServiceAddress address, int sourceDevice)
        {
            SignalProtocolAddress?uuidAddress = address.Uuid.HasValue ? new SignalProtocolAddress(address.Uuid.Value.ToString(), (uint)sourceDevice) : null;
            SignalProtocolAddress?e164Address = address.GetNumber() != null ? new SignalProtocolAddress(address.GetNumber(), (uint)sourceDevice) : null;

            if (uuidAddress != null && store.ContainsSession(uuidAddress))
            {
                return(uuidAddress);
            }
            else if (e164Address != null && store.ContainsSession(e164Address))
            {
                return(e164Address);
            }
            else
            {
                return(new SignalProtocolAddress(address.GetIdentifier(), (uint)sourceDevice));
            }
        }
Exemple #2
0
        private PreKeyBundle createBobPreKeyBundle(SignalProtocolStore bobStore)
        {
            ECKeyPair bobUnsignedPreKey   = Curve.generateKeyPair();
            int       bobUnsignedPreKeyId = new Random().Next((int)Medium.MAX_VALUE);

            byte[] bobSignature = Curve.calculateSignature(bobStore.GetIdentityKeyPair().getPrivateKey(),
                                                           bobSignedPreKey.getPublicKey().serialize());

            PreKeyBundle bobPreKeyBundle = new PreKeyBundle(1, 1,
                                                            (uint)bobUnsignedPreKeyId, bobUnsignedPreKey.getPublicKey(),
                                                            bobSignedPreKeyId, bobSignedPreKey.getPublicKey(),
                                                            bobSignature, bobStore.GetIdentityKeyPair().getPublicKey());

            bobStore.StoreSignedPreKey(bobSignedPreKeyId, new SignedPreKeyRecord(bobSignedPreKeyId, (ulong)DateTime.UtcNow.Ticks, bobSignedPreKey, bobSignature));
            bobStore.StorePreKey((uint)bobUnsignedPreKeyId, new PreKeyRecord((uint)bobUnsignedPreKeyId, bobUnsignedPreKey));

            return(bobPreKeyBundle);
        }
Exemple #3
0
        private PreKeyBundle createAlicePreKeyBundle(SignalProtocolStore aliceStore)
        {
            ECKeyPair aliceUnsignedPreKey   = Curve.generateKeyPair();
            int       aliceUnsignedPreKeyId = new Random().Next((int)Medium.MAX_VALUE);

            byte[] aliceSignature = Curve.calculateSignature(aliceStore.GetIdentityKeyPair().getPrivateKey(),
                                                             aliceSignedPreKey.getPublicKey().serialize());

            PreKeyBundle alicePreKeyBundle = new PreKeyBundle(1, 1,
                                                              (uint)aliceUnsignedPreKeyId, aliceUnsignedPreKey.getPublicKey(),
                                                              aliceSignedPreKeyId, aliceSignedPreKey.getPublicKey(),
                                                              aliceSignature, aliceStore.GetIdentityKeyPair().getPublicKey());

            aliceStore.StoreSignedPreKey(aliceSignedPreKeyId, new SignedPreKeyRecord(aliceSignedPreKeyId, (ulong)DateTime.UtcNow.Ticks, aliceSignedPreKey, aliceSignature));
            aliceStore.StorePreKey((uint)aliceUnsignedPreKeyId, new PreKeyRecord((uint)aliceUnsignedPreKeyId, aliceUnsignedPreKey));

            return(alicePreKeyBundle);
        }
 /// <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;
 }
Exemple #5
0
        public byte[] Encrypt(SignalProtocolAddress destinationAddress, SenderCertificate senderCertificate, byte[] paddedPlaintext)
        {
            CiphertextMessage message       = new SessionCipher(SignalProtocolStore, destinationAddress).encrypt(paddedPlaintext);
            IdentityKeyPair   ourIdentity   = SignalProtocolStore.GetIdentityKeyPair();
            ECPublicKey       theirIdentity = SignalProtocolStore.GetIdentity(destinationAddress).getPublicKey();

            ECKeyPair ephemeral = Curve.generateKeyPair();

            byte[]        ephemeralSalt = ByteUtil.combine(Encoding.ASCII.GetBytes("UnidentifiedDelivery"), theirIdentity.serialize(), ephemeral.getPublicKey().serialize());
            EphemeralKeys ephemeralKeys = CalculateEphemeralKeys(theirIdentity, ephemeral.getPrivateKey(), ephemeralSalt);

            byte[] staticKeyCiphertext = Encrypt(ephemeralKeys.CipherKey, ephemeralKeys.MacKey, ourIdentity.getPublicKey().getPublicKey().serialize());

            byte[]     staticSalt = ByteUtil.combine(ephemeralKeys.ChainKey, staticKeyCiphertext);
            StaticKeys staticKeys = CalculateStaticKeys(theirIdentity, ourIdentity.getPrivateKey(), staticSalt);
            UnidentifiedSenderMessageContent content = new UnidentifiedSenderMessageContent((int)message.getType(), senderCertificate, message.serialize());

            byte[] messageBytes = Encrypt(staticKeys.CipherKey, staticKeys.MacKey, content.Serialized);

            return(new UnidentifiedSenderMessage(ephemeral.getPublicKey(), staticKeyCiphertext, messageBytes).Serialized);
        }
Exemple #6
0
        private void runInteraction(SignalProtocolStore aliceStore, SignalProtocolStore bobStore)
        {
            SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
            SessionCipher bobSessionCipher   = new SessionCipher(bobStore, ALICE_ADDRESS);

            String            originalMessage = "smert ze smert";
            CiphertextMessage aliceMessage    = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage));

            Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, aliceMessage.getType());

            byte[] plaintext = bobSessionCipher.decrypt(new SignalMessage(aliceMessage.serialize()));
            Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext));

            CiphertextMessage bobMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage));

            Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, bobMessage.getType());

            plaintext = aliceSessionCipher.decrypt(new SignalMessage(bobMessage.serialize()));
            Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext));

            for (int i = 0; i < 10; i++)
            {
                String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
                                         "We mean that man first of all exists, encounters himself, " +
                                         "surges up in the world--and defines himself aftward. " + i);
                CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage));

                byte[] loopingPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceLoopingMessage.serialize()));
                Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext));
            }

            for (int i = 0; i < 10; i++)
            {
                String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
                                         "We mean that man first of all exists, encounters himself, " +
                                         "surges up in the world--and defines himself aftward. " + i);
                CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage));

                byte[] loopingPlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobLoopingMessage.serialize()));
                Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext));
            }

            HashSet <Pair <String, CiphertextMessage> > aliceOutOfOrderMessages = new HashSet <Pair <String, CiphertextMessage> >();

            for (int i = 0; i < 10; i++)
            {
                String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
                                         "We mean that man first of all exists, encounters himself, " +
                                         "surges up in the world--and defines himself aftward. " + i);
                CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage));

                aliceOutOfOrderMessages.Add(new Pair <String, CiphertextMessage>(loopingMessage, aliceLoopingMessage));
            }

            for (int i = 0; i < 10; i++)
            {
                String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
                                         "We mean that man first of all exists, encounters himself, " +
                                         "surges up in the world--and defines himself aftward. " + i);
                CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage));

                byte[] loopingPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceLoopingMessage.serialize()));
                Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext));
            }

            for (int i = 0; i < 10; i++)
            {
                String            loopingMessage    = ("You can only desire based on what you know: " + i);
                CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage));

                byte[] loopingPlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobLoopingMessage.serialize()));
                Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext));
            }

            foreach (Pair <String, CiphertextMessage> aliceOutOfOrderMessage in aliceOutOfOrderMessages)
            {
                byte[] outOfOrderPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceOutOfOrderMessage.second().serialize()));
                Assert.AreEqual(aliceOutOfOrderMessage.first(), Encoding.UTF8.GetString(outOfOrderPlaintext));
            }
        }
Exemple #7
0
 public BobDecryptionCallback(SignalProtocolStore bobStore, String originalMessage)
 {
     this.bobStore        = bobStore;
     this.originalMessage = originalMessage;
 }
 /**
  * Constructs a SessionBuilder
  * @param store The {@link SignalProtocolStore} to store all state information in.
  * @param remoteAddress The address of the remote user to build a session with.
  */
 public SessionBuilder(SignalProtocolStore store, SignalProtocolAddress remoteAddress)
     : this(store, store, store, store, remoteAddress)
 {
 }
 public SignalServiceCipher(SignalServiceAddress localAddress, SignalProtocolStore signalProtocolStore)
 {
     this.signalProtocolStore = signalProtocolStore;
     this.localAddress        = localAddress;
 }
Exemple #10
0
 private bool isSessionIdEqual(SignalProtocolStore aliceStore, SignalProtocolStore bobStore)
 {
     return(ByteUtil.isEqual(aliceStore.LoadSession(BOB_ADDRESS).getSessionState().getAliceBaseKey(),
                             bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getAliceBaseKey()));
 }
Exemple #11
0
        public (SignalProtocolAddress, byte[]) Decrypt(CertificateValidator validator, byte[] ciphertext, long timestamp)
        {
            UnidentifiedSenderMessageContent content;

            try
            {
                IdentityKeyPair           ourIdentity = SignalProtocolStore.GetIdentityKeyPair();
                UnidentifiedSenderMessage wrapper     = new UnidentifiedSenderMessage(ciphertext);
                byte[]        ephemeralSalt           = ByteUtil.combine(Encoding.ASCII.GetBytes("UnidentifiedDelivery"), ourIdentity.getPublicKey().getPublicKey().serialize(), wrapper.Ephemeral.serialize());
                EphemeralKeys ephemeralKeys           = CalculateEphemeralKeys(wrapper.Ephemeral, ourIdentity.getPrivateKey(), ephemeralSalt);
                byte[]        staticKeyBytes          = Decrypt(ephemeralKeys.CipherKey, ephemeralKeys.MacKey, wrapper.EncryptedStatic);

                ECPublicKey staticKey    = Curve.decodePoint(staticKeyBytes, 0);
                byte[]      staticSalt   = ByteUtil.combine(ephemeralKeys.ChainKey, wrapper.EncryptedStatic);
                StaticKeys  staticKeys   = CalculateStaticKeys(staticKey, ourIdentity.getPrivateKey(), staticSalt);
                byte[]      messageBytes = Decrypt(staticKeys.CipherKey, staticKeys.MacKey, wrapper.EncryptedMessage);

                content = new UnidentifiedSenderMessageContent(messageBytes);
                validator.Validate(content.SenderCertificate, timestamp);

                if (!Enumerable.SequenceEqual(content.SenderCertificate.Key.serialize(), staticKeyBytes))
                {
                    throw new libsignal.InvalidKeyException("Sender's certificate key does not match key used in message");
                }

                if (content.SenderCertificate.Sender == LocalAddress.Name &&
                    content.SenderCertificate.SenderDeviceId == LocalAddress.DeviceId)
                {
                    throw new SelfSendException();
                }
            }
            catch (libsignal.InvalidKeyException e)
            {
                throw new InvalidMetadataMessageException(e);
            }
            catch (InvalidCertificateException e)
            {
                throw new InvalidMetadataMessageException(e);
            }
            catch (InvalidMacException e)
            {
                throw new InvalidMetadataMessageException(e);
            }

            try
            {
                return(new SignalProtocolAddress(content.SenderCertificate.Sender, (uint)content.SenderCertificate.SenderDeviceId),
                       Decrypt(content));
            }
            catch (InvalidMessageException e)
            {
                throw new ProtocolInvalidMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (libsignal.InvalidKeyException e)
            {
                throw new ProtocolInvalidKeyException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (NoSessionException e)
            {
                throw new ProtocolNoSessionException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (LegacyMessageException e)
            {
                throw new ProtocolLegacyMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (InvalidVersionException e)
            {
                throw new ProtocolInvalidVersionException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (DuplicateMessageException e)
            {
                throw new ProtocolDuplicateMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (InvalidKeyIdException e)
            {
                throw new ProtocolInvalidKeyIdException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (UntrustedIdentityException e)
            {
                throw new ProtocolUntrustedIdentityException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
        }
Exemple #12
0
 public SealedSessionCipher(SignalProtocolStore store, SignalProtocolAddress localAddress)
 {
     SignalProtocolStore = store;
     LocalAddress        = localAddress;
 }