//--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- /// <summary> /// Encrypts the content of MESSAGE with the given SessionCipher and saves the result in BASE_64_PAYLOAD. /// </summary> /// <param name="omemoSession">A storage object containing all SessionCipher for the target OMEMO devices.</param> /// <param name="sourceDeviceId">The sender OMEMO device id.</param> public void encrypt(OmemoSession omemoSession, uint sourceDeviceId) { SOURCE_DEVICE_ID = sourceDeviceId; // 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(MESSAGE)); BASE_64_PAYLOAD = Convert.ToBase64String(encryptedData); BASE_64_IV = 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); // 4. Encrypt the key/authTag pair with libsignal for each deviceId: KEYS = new List <OmemoKey>(); Logger.Debug("[OmemoMessageMessage]: Source device id: " + SOURCE_DEVICE_ID); Logger.Debug("[OmemoMessageMessage]: Encrypting for remote devices."); encryptForDevices(omemoSession.DEVICE_SESSIONS_REMOTE, keyAuthTag); Logger.Debug("[OmemoMessageMessage]: Encrypting for own devices."); encryptForDevices(omemoSession.DEVICE_SESSIONS_OWN, keyAuthTag); ENCRYPTED = true; }
//--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- /// <summary> /// Encrypts the content of MESSAGE with the given SessionCipher and saves the result in BASE_64_PAYLOAD. /// </summary> /// <param name="omemoSession">A storage object containing all SessionCipher for the target OMEMO devices.</param> /// <param name="sourceDeviceId">The sender OMEMO device id.</param> public void encrypt(OmemoSession omemoSession, uint sourceDeviceId) { SOURCE_DEVICE_ID = sourceDeviceId; // 1. Generate a new AES-128 GCM key/iv: Aes128Gcm aes128Gcm = new Aes128Gcm(); aes128Gcm.generateKey(); aes128Gcm.generateIv(); // 2. Encrypt the message using the Aes128Gcm instance: byte[] encryptedData = aes128Gcm.encrypt(Encoding.Unicode.GetBytes(MESSAGE)); BASE_64_PAYLOAD = Convert.ToBase64String(encryptedData); BASE_64_IV = 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); // 4. Encrypt the key/authTag pair with libsignal for each deviceId: KEYS = new List <OmemoKey>(); CiphertextMessage ciphertextMessage; foreach (KeyValuePair <uint, SessionCipher> pair in omemoSession.DEVICE_SESSIONS) { ciphertextMessage = pair.Value.encrypt(keyAuthTag); // Create a new OmemoKey object with the target device id, whether it's the first time the session got established and the encrypted key: OmemoKey key = new OmemoKey(pair.Key, ciphertextMessage is PreKeySignalMessage, Convert.ToBase64String(ciphertextMessage.serialize())); KEYS.Add(key); } ENCRYPTED = true; }
private async Task sendAllOutstandingMessagesAsync(OmemoSession omemoSession) { Tuple <List <OmemoMessageMessage>, OmemoSessionBuildHelper> cache = MESSAGE_CACHE[omemoSession.CHAT_JID]; foreach (OmemoMessageMessage msg in cache.Item1) { msg.encrypt(omemoSession, CONNECTION.account.omemoDeviceId); await CONNECTION.SendAsync(msg, false); } MESSAGE_CACHE.Remove(omemoSession.CHAT_JID); Logger.Info("[OMEMO HELPER] Send all outstanding OMEMO messages for: " + omemoSession.CHAT_JID + " to " + omemoSession.DEVICE_SESSIONS_OWN.Count + " own and " + omemoSession.DEVICE_SESSIONS_REMOTE.Count + " remote recipient(s)."); }
private async Task sendAllOutstandingMessagesAsync(OmemoSession omemoSession) { Tuple <List <OmemoMessageMessage>, OmemoSessionBuildHelper> cache = MESSAGE_CACHE[omemoSession.CHAT_JID]; foreach (OmemoMessageMessage msg in cache.Item1) { msg.encrypt(omemoSession, CONNECTION.account.omemoDeviceId); await CONNECTION.sendAsync(msg, true, false); } cache.Item2.Dispose(); MESSAGE_CACHE.Remove(omemoSession.CHAT_JID); Logger.Info("[OMEMO HELPER] Send all outstanding OMEMO messages for: " + omemoSession.CHAT_JID); }
//--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- /// <summary> /// Basic Constructor /// </summary> /// <history> /// 10/08/2018 Created [Fabian Sauter] /// </history> internal OmemoSessionBuildResult(OmemoSession session) { SESSION = session; SUCCESS = true; }
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); }