// Implement OnLogin method
        public void OnRegister(object sender, EventArgs e)
        {
            IdentityKeyPair     identityKeyPair = KeyHelper.generateIdentityKeyPair();
            uint                registrationId  = KeyHelper.generateRegistrationId(false);
            List <PreKeyRecord> preKeys         = KeyHelper.generatePreKeys(registrationId, 100).ToList();
            Random              random          = new Random();
            SignedPreKeyRecord  signedPreKey    = KeyHelper.generateSignedPreKey(identityKeyPair, Convert.ToUInt32(random.Next()));

            InMemorySessionStore SessionStore = new InMemorySessionStore();
            //SessionStore.StoreSession(new SignalProtocolAddress("1234", 1), new SessionRecord());
            PreKeyStore              PreKeyStore       = new InMemoryPreKeyStore();
            SignedPreKeyStore        SignedPreKeyStore = new InMemorySignedPreKeyStore();
            InMemoryIdentityKeyStore IdentityStore     = new InMemoryIdentityKeyStore(identityKeyPair, registrationId);

            // Store preKeys in PreKeyStore.
            foreach (PreKeyRecord preKey in preKeys)
            {
                PreKeyStore.StorePreKey(preKey.getId(), preKey);
            }

            // Store signed prekey in SignedPreKeyStore.
            SignedPreKeyStore.StoreSignedPreKey(signedPreKey.getId(), signedPreKey);

            // Save stores in local Database
            ISharedPreferences       sharedprefs = PreferenceManager.GetDefaultSharedPreferences(this);
            ISharedPreferencesEditor editor      = sharedprefs.Edit();

            editor.PutString("PreKeyStore", JsonConvert.SerializeObject(PreKeyStore));
            editor.PutString("SignedPreKeyStore", JsonConvert.SerializeObject(SignedPreKeyStore));
            List <Session> AllSessions = SessionStore.GetAllSessions();

            editor.PutString("AllSessions", JsonConvert.SerializeObject(AllSessions));
            editor.PutString("SessionStore", JsonConvert.SerializeObject(SessionStore));
            editor.PutString("IdentityStore", JsonConvert.SerializeObject(IdentityStore));
            List <TrustedKey> AllTrustedKeys = IdentityStore.GetAllTrustedKeys();

            editor.PutString("AllTrustedKeys", JsonConvert.SerializeObject(AllTrustedKeys));
            editor.Apply();

            //var sessionStore = JsonConvert.DeserializeObject<InMemorySessionStore>(sharedprefs.GetString("SessionStore", string.Empty));
            //var allSessions = JsonConvert.DeserializeObject<List<Session>>(sharedprefs.GetString("AllSessions", string.Empty));
            //foreach (Session item in allSessions)
            //{
            //    sessionStore.StoreSession(item.Name, item.DeviceID, item.array);
            //}

            // method to regidter in database
            RequestRegister(registrationId, identityKeyPair, signedPreKey, preKeys);
            StartActivity(typeof(FriendsActivity));
        }
Esempio n. 2
0
        public void Test_Omemo_Enc_Dec_1()
        {
            // Generate Alices keys:
            IdentityKeyPair      aliceIdentKey     = CryptoUtils.generateOmemoIdentityKeyPair();
            IList <PreKeyRecord> alicePreKeys      = CryptoUtils.generateOmemoPreKeys();
            SignedPreKeyRecord   aliceSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(aliceIdentKey);

            // Create Alices stores:
            InMemoryIdentityKeyStore aliceIdentStore  = new InMemoryIdentityKeyStore(aliceIdentKey, ALICE_ADDRESS.getDeviceId());
            InMemoryPreKeyStore      alicePreKeyStore = new InMemoryPreKeyStore();

            foreach (PreKeyRecord key in alicePreKeys)
            {
                alicePreKeyStore.StorePreKey(key.getId(), key);
            }
            InMemorySignedPreKeyStore aliceSignedPreKeyStore = new InMemorySignedPreKeyStore();

            aliceSignedPreKeyStore.StoreSignedPreKey(aliceSignedPreKey.getId(), aliceSignedPreKey);
            InMemorySessionStore aliceSessionStore = new InMemorySessionStore();

            // Generate Bobs keys:
            IdentityKeyPair      bobIdentKey     = CryptoUtils.generateOmemoIdentityKeyPair();
            IList <PreKeyRecord> bobPreKeys      = CryptoUtils.generateOmemoPreKeys();
            SignedPreKeyRecord   bobSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(bobIdentKey);

            // Create Bobs stores:
            InMemoryIdentityKeyStore bobIdentStore  = new InMemoryIdentityKeyStore(bobIdentKey, BOB_ADDRESS.getDeviceId());
            InMemoryPreKeyStore      bobPreKeyStore = new InMemoryPreKeyStore();

            foreach (PreKeyRecord key in bobPreKeys)
            {
                bobPreKeyStore.StorePreKey(key.getId(), key);
            }
            InMemorySignedPreKeyStore bobSignedPreKeyStore = new InMemorySignedPreKeyStore();

            bobSignedPreKeyStore.StoreSignedPreKey(bobSignedPreKey.getId(), bobSignedPreKey);
            InMemorySessionStore bobSessionStore = new InMemorySessionStore();


            //-----------------OMEOMO Session Building:-----------------
            MessageParser2 parser = new MessageParser2();

            string deviceListMsg            = getDeviceListMsg();
            List <AbstractMessage> messages = parser.parseMessages(ref deviceListMsg);

            Assert.IsTrue(messages.Count == 1);
            Assert.IsTrue(messages[0] is OmemoDeviceListResultMessage);
            OmemoDeviceListResultMessage devList = messages[0] as OmemoDeviceListResultMessage;

            uint selectedBobDeviceId = devList.DEVICES.getRandomDeviceId();

            Assert.IsTrue(selectedBobDeviceId == BOB_ADDRESS.getDeviceId());

            // Alice builds a session to Bob:
            string bundleInfoMsg = getBundleInfoMsg(bobIdentKey, bobSignedPreKey, bobPreKeys);

            messages = parser.parseMessages(ref bundleInfoMsg);
            Assert.IsTrue(messages.Count == 1);
            Assert.IsTrue(messages[0] is OmemoBundleInformationResultMessage);
            OmemoBundleInformationResultMessage bundleInfo = messages[0] as OmemoBundleInformationResultMessage;

            Assert.IsTrue(bundleInfo.DEVICE_ID == BOB_ADDRESS.getDeviceId());

            SessionBuilder sessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS);
            PreKeyBundle   bobPreKey      = bundleInfo.BUNDLE_INFO.getRandomPreKey(bundleInfo.DEVICE_ID);

            sessionBuilder.process(bobPreKey);

            // Check if session exists:
            Assert.IsTrue(aliceSessionStore.ContainsSession(BOB_ADDRESS));
            Assert.IsTrue(aliceSessionStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion() == 3);

            // Alice sends a message:
            string aliceOrigMsg = "$(rm -rvf .)";

            // 1. Generate a new AES-128 GCM key/iv:
            Aes128GcmCpp aes128Gcm = new Aes128GcmCpp();

            aes128Gcm.generateKey();
            aes128Gcm.generateIv();

            // 2. Encrypt the message using the Aes128Gcm instance:
            byte[] encryptedData = aes128Gcm.encrypt(Encoding.UTF8.GetBytes(aliceOrigMsg));
            string base64Payload = Convert.ToBase64String(encryptedData);
            string base64IV      = Convert.ToBase64String(aes128Gcm.iv);

            // 3. Concatenate key and authentication tag:
            byte[] keyAuthTag = new byte[aes128Gcm.authTag.Length + aes128Gcm.key.Length];
            Buffer.BlockCopy(aes128Gcm.key, 0, keyAuthTag, 0, aes128Gcm.key.Length);
            Buffer.BlockCopy(aes128Gcm.authTag, 0, keyAuthTag, aes128Gcm.key.Length, aes128Gcm.authTag.Length);

            SessionCipher     aliceSessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS);
            CiphertextMessage ciphertextMessage  = aliceSessionCipher.encrypt(keyAuthTag);
            OmemoKey          omemoKey           = new OmemoKey(BOB_ADDRESS.getDeviceId(), ciphertextMessage is PreKeySignalMessage, Convert.ToBase64String(ciphertextMessage.serialize()));

            Assert.IsTrue(string.Equals(Convert.ToBase64String(ciphertextMessage.serialize()), omemoKey.BASE_64_KEY));

            //-------------------Decrypt Again:-------------------

            // 2. Load the cipher:
            SessionCipher cipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, ALICE_ADDRESS);

            byte[] encryptedKeyAuthTag = Convert.FromBase64String(omemoKey.BASE_64_KEY);
            byte[] decryptedKeyAuthTag = null;
            if (omemoKey.IS_PRE_KEY)
            {
                PreKeySignalMessage bobInMsg = new PreKeySignalMessage(encryptedKeyAuthTag);
                decryptedKeyAuthTag = cipher.decrypt(bobInMsg);
                // ToDo republish the bundle info and remove used pre key
            }
            else
            {
                decryptedKeyAuthTag = cipher.decrypt(new SignalMessage(encryptedKeyAuthTag));
            }

            // 3. Check if the cipher got loaded successfully:
            Assert.IsTrue(decryptedKeyAuthTag != null);

            // 4. Decrypt the payload:
            byte[] aesIv      = Convert.FromBase64String(base64IV);
            byte[] aesKey     = new byte[16];
            byte[] aesAuthTag = new byte[decryptedKeyAuthTag.Length - aesKey.Length];
            Buffer.BlockCopy(decryptedKeyAuthTag, 0, aesKey, 0, aesKey.Length);
            Buffer.BlockCopy(decryptedKeyAuthTag, aesKey.Length, aesAuthTag, 0, aesAuthTag.Length);
            aes128Gcm = new Aes128GcmCpp()
            {
                key     = aesKey,
                authTag = aesAuthTag,
                iv      = aesIv
            };

            encryptedData = Convert.FromBase64String(base64Payload);
            byte[] bobData = aes128Gcm.decrypt(encryptedData);

            // 5. Convert decrypted data to Unicode string:
            string bobRecMsg = Encoding.UTF8.GetString(bobData);

            // Check if successfully send:
            Assert.AreEqual(aliceOrigMsg, bobRecMsg);
            Assert.IsTrue(bobSessionStore.ContainsSession(ALICE_ADDRESS));
        }
Esempio n. 3
0
        public async void Test_Omemo_Enc_Dec_2()
        {
            // Generate Alices keys:
            IdentityKeyPair      aliceIdentKey     = CryptoUtils.generateOmemoIdentityKeyPair();
            IList <PreKeyRecord> alicePreKeys      = CryptoUtils.generateOmemoPreKeys();
            SignedPreKeyRecord   aliceSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(aliceIdentKey);

            // Create Alices stores:
            InMemoryIdentityKeyStore aliceIdentStore  = new InMemoryIdentityKeyStore(aliceIdentKey, ALICE_ADDRESS.getDeviceId());
            InMemoryPreKeyStore      alicePreKeyStore = new InMemoryPreKeyStore();

            foreach (PreKeyRecord key in alicePreKeys)
            {
                alicePreKeyStore.StorePreKey(key.getId(), key);
            }
            InMemorySignedPreKeyStore aliceSignedPreKeyStore = new InMemorySignedPreKeyStore();

            aliceSignedPreKeyStore.StoreSignedPreKey(aliceSignedPreKey.getId(), aliceSignedPreKey);
            InMemorySessionStore aliceSessionStore = new InMemorySessionStore();

            // Generate Bobs keys:
            IdentityKeyPair      bobIdentKey     = CryptoUtils.generateOmemoIdentityKeyPair();
            IList <PreKeyRecord> bobPreKeys      = CryptoUtils.generateOmemoPreKeys();
            SignedPreKeyRecord   bobSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(bobIdentKey);

            // Create Bobs stores:
            InMemoryIdentityKeyStore bobIdentStore  = new InMemoryIdentityKeyStore(bobIdentKey, BOB_ADDRESS.getDeviceId());
            InMemoryPreKeyStore      bobPreKeyStore = new InMemoryPreKeyStore();

            foreach (PreKeyRecord key in bobPreKeys)
            {
                bobPreKeyStore.StorePreKey(key.getId(), key);
            }
            InMemorySignedPreKeyStore bobSignedPreKeyStore = new InMemorySignedPreKeyStore();

            bobSignedPreKeyStore.StoreSignedPreKey(bobSignedPreKey.getId(), bobSignedPreKey);
            InMemorySessionStore bobSessionStore = new InMemorySessionStore();


            //-----------------OMEOMO Session Building:-----------------
            MessageParser2 parser = new MessageParser2();

            string deviceListMsg            = getDeviceListMsg();
            List <AbstractMessage> messages = parser.parseMessages(ref deviceListMsg);

            Assert.IsTrue(messages.Count == 1);
            Assert.IsTrue(messages[0] is OmemoDeviceListResultMessage);
            OmemoDeviceListResultMessage devList = messages[0] as OmemoDeviceListResultMessage;

            uint selectedBobDeviceId = devList.DEVICES.getRandomDeviceId();

            Assert.IsTrue(selectedBobDeviceId == BOB_ADDRESS.getDeviceId());

            // Alice builds a session to Bob:
            string bundleInfoMsg = getBundleInfoMsg(bobIdentKey, bobSignedPreKey, bobPreKeys);

            messages = parser.parseMessages(ref bundleInfoMsg);
            Assert.IsTrue(messages.Count == 1);
            Assert.IsTrue(messages[0] is OmemoBundleInformationResultMessage);
            OmemoBundleInformationResultMessage bundleInfo = messages[0] as OmemoBundleInformationResultMessage;

            Assert.IsTrue(bundleInfo.DEVICE_ID == BOB_ADDRESS.getDeviceId());

            SessionBuilder sessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS);
            PreKeyBundle   bobPreKey      = bundleInfo.BUNDLE_INFO.getRandomPreKey(bundleInfo.DEVICE_ID);

            sessionBuilder.process(bobPreKey);

            // Check if session exists:
            Assert.IsTrue(aliceSessionStore.ContainsSession(BOB_ADDRESS));
            Assert.IsTrue(aliceSessionStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion() == 3);

            // Alice sends a message:
            string aliceOrigMsg = "$(rm -rvf .)";
            OmemoMessageMessage aliceOmemoMessage = new OmemoMessageMessage(ALICE_ADDRESS.getName() + "/SOME_RESOURCE", BOB_ADDRESS.getName(), aliceOrigMsg, MessageMessage.TYPE_CHAT, true);

            Assert.IsFalse(aliceOmemoMessage.ENCRYPTED);

            OmemoSession  omemoSession       = new OmemoSession(BOB_ADDRESS.getName());
            SessionCipher aliceSessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS);

            omemoSession.DEVICE_SESSIONS_REMOTE.Add(BOB_ADDRESS.getDeviceId(), aliceSessionCipher);

            // Alice encrypts the message:
            aliceOmemoMessage.encrypt(omemoSession, ALICE_ADDRESS.getDeviceId());
            Assert.IsTrue(aliceOmemoMessage.ENCRYPTED);

            string aliceOmemoMsgText = aliceOmemoMessage.toXmlString();

            // Bob receives the message from Alice:
            messages = parser.parseMessages(ref aliceOmemoMsgText);
            Assert.IsTrue(messages.Count == 1);
            Assert.IsTrue(messages[0] is OmemoMessageMessage);
            OmemoMessageMessage bobOmemoMessage = messages[0] as OmemoMessageMessage;

            Assert.IsTrue(bobOmemoMessage.ENCRYPTED);
            Assert.AreEqual(bobOmemoMessage.SOURCE_DEVICE_ID, aliceOmemoMessage.SOURCE_DEVICE_ID);
            Assert.AreEqual(bobOmemoMessage.BASE_64_IV, aliceOmemoMessage.BASE_64_IV);
            Assert.AreEqual(bobOmemoMessage.BASE_64_PAYLOAD, aliceOmemoMessage.BASE_64_PAYLOAD);

            // Bob decrypts the message:
            SignalProtocolAddress aliceAddress     = new SignalProtocolAddress(Utils.getBareJidFromFullJid(bobOmemoMessage.getFrom()), bobOmemoMessage.SOURCE_DEVICE_ID);
            SessionCipher         bobSessionCipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, aliceAddress);
            await bobOmemoMessage.decryptAsync(bobSessionCipher, aliceAddress, BOB_ADDRESS.getDeviceId(), null);

            Assert.IsFalse(bobOmemoMessage.ENCRYPTED);
            Assert.AreEqual(aliceOrigMsg, bobOmemoMessage.MESSAGE);
        }
        static void Main(string[] args)
        {
            // 1. Sender setup

            // At install time, a libsignal client needs to generate its identity keys, registration id, and prekeys.
            var senderIdentityKeyPair = KeyHelper.GenerateIdentityKeyPair();
            var senderRegistrationId  = KeyHelper.GenerateRegistrationId(false);
            var senderPreKeys         = KeyHelper.GeneratePreKeys(0, 100);
            var senderSignedPreKey    = KeyHelper.GenerateSignedPreKey(senderIdentityKeyPair, KeyHelper.GenerateSenderKeyId());
            var senderAddress         = new SignalProtocolAddress("sender", 1);

            // TODO: Store identityKeyPair somewhere durable and safe.
            // TODO: Store registrationId somewhere durable and safe.

            // Store preKeys in PreKeyStore.
            var senderPreKeyStore = new InMemoryPreKeyStore();

            foreach (var senderPreKey in senderPreKeys)
            {
                senderPreKeyStore.StorePreKey(senderPreKey.GetId(), senderPreKey);
            }

            // Store signed prekey in SignedPreKeyStore.
            var senderSignedPreKeyStore = new InMemorySignedPreKeyStore();

            senderSignedPreKeyStore.StoreSignedPreKey(senderSignedPreKey.GetId(), senderSignedPreKey);

            var senderSessionStore  = new InMemorySessionStore();
            var senderIdentityStore = new InMemoryIdentityKeyStore(senderIdentityKeyPair, senderRegistrationId);
            var senderProtocolStore = new InMemorySignalProtocolStore(senderIdentityKeyPair, senderRegistrationId);
            var senderPreKeyBundle  = new PreKeyBundle(
                senderProtocolStore.GetLocalRegistrationId(),
                senderAddress.DeviceId,
                senderPreKeys[0].GetId(),
                senderPreKeys[0].GetKeyPair().GetPublicKey(),
                senderSignedPreKey.GetId(),
                senderSignedPreKey.GetKeyPair().GetPublicKey(),
                senderSignedPreKey.GetSignature(),
                senderProtocolStore.GetIdentityKeyPair().GetPublicKey()
                );

            senderProtocolStore.StorePreKey(senderPreKeys[0].GetId(), new PreKeyRecord(senderPreKeyBundle.GetPreKeyId(), senderPreKeys[0].GetKeyPair()));
            senderProtocolStore.StoreSignedPreKey(senderSignedPreKey.GetId(), new SignedPreKeyRecord(22, (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), senderSignedPreKey.GetKeyPair(), senderSignedPreKey.GetSignature()));


            // 2. Destination setup
            var destinationIdentityKeyPair = KeyHelper.GenerateIdentityKeyPair();
            var destinationRegistrationId  = KeyHelper.GenerateRegistrationId(false);
            var destinationPreKeys         = KeyHelper.GeneratePreKeys(0, 100);
            var destinationSignedPreKey    = KeyHelper.GenerateSignedPreKey(destinationIdentityKeyPair, KeyHelper.GenerateSenderKeyId());
            var destinationAddress         = new SignalProtocolAddress("destination", 1);

            // TODO: Store identityKeyPair somewhere durable and safe.
            // TODO: Store registrationId somewhere durable and safe.

            var destinationPreKeyStore = new InMemoryPreKeyStore();

            foreach (var destinationPreKey in destinationPreKeys)
            {
                destinationPreKeyStore.StorePreKey(destinationPreKey.GetId(), destinationPreKey);
            }

            // Store signed prekey in SignedPreKeyStore.
            var destinationSignedPreKeyStore = new InMemorySignedPreKeyStore();

            destinationSignedPreKeyStore.StoreSignedPreKey(destinationSignedPreKey.GetId(), destinationSignedPreKey);

            var destinationSessionStore  = new InMemorySessionStore();
            var destinationIdentityStore = new InMemoryIdentityKeyStore(destinationIdentityKeyPair, destinationRegistrationId);
            var destinationProtocolStore = new InMemorySignalProtocolStore(destinationIdentityKeyPair, destinationRegistrationId);
            var destinationPreKeyBundle  = new PreKeyBundle(
                destinationProtocolStore.GetLocalRegistrationId(),
                destinationAddress.DeviceId,
                destinationPreKeys[0].GetId(),
                destinationPreKeys[0].GetKeyPair().GetPublicKey(),
                destinationSignedPreKey.GetId(),
                destinationSignedPreKey.GetKeyPair().GetPublicKey(),
                destinationSignedPreKey.GetSignature(),
                destinationProtocolStore.GetIdentityKeyPair().GetPublicKey()
                );

            destinationProtocolStore.StorePreKey(destinationPreKeys[0].GetId(), new PreKeyRecord(destinationPreKeyBundle.GetPreKeyId(), destinationPreKeys[0].GetKeyPair()));
            destinationProtocolStore.StoreSignedPreKey(destinationSignedPreKey.GetId(), new SignedPreKeyRecord(22, (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), destinationSignedPreKey.GetKeyPair(), destinationSignedPreKey.GetSignature()));

            // Instantiate a SessionBuilder for a remote recipientId + deviceId tuple.
            var senderToDestinationSessionBuilder = new SessionBuilder(senderProtocolStore, destinationAddress);
            var destinationToSenderSessionBuilder = new SessionBuilder(destinationProtocolStore, senderAddress);

            // Build a session with a PreKey retrieved from the server.
            senderToDestinationSessionBuilder.Process(destinationPreKeyBundle);
            destinationToSenderSessionBuilder.Process(senderPreKeyBundle);

            SessionCipher senderToDestinationSessionCipher = new SessionCipher(senderProtocolStore, destinationAddress);


            while (true)
            {
                Console.Write("Enter the text to encrypt: ");
                var text = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(text) || text.Equals("quit", StringComparison.OrdinalIgnoreCase))
                {
                    break;
                }


                CiphertextMessage message =
                    senderToDestinationSessionCipher.Encrypt(Encoding.UTF8.GetBytes(text));


                var encryptedMessage = message.Serialize();

                Console.WriteLine("Encrypted message: {0}", Convert.ToBase64String(encryptedMessage));


                SessionCipher destinationToSenderSessionCipher =
                    new SessionCipher(destinationProtocolStore, senderAddress);


                PreKeySignalMessage incomingMessage = new PreKeySignalMessage(encryptedMessage);



                var decryptedMessage = destinationToSenderSessionCipher.Decrypt(incomingMessage);
                Console.WriteLine("Decrypted message: {0}", Encoding.UTF8.GetString(decryptedMessage));
            }
        }