public OmemoDeviceTable(SignalProtocolAddress device, string accountId) { this.id = generateId(accountId, device.getName(), device.getDeviceId()); this.accountId = accountId; this.name = device.getName(); this.deviceId = device.getDeviceId(); }
public bool ContainsSession(SignalProtocolAddress address) { var name = address.getName(); var deviceId = address.getDeviceId(); var query = conn.Table <Session>().Where(v => v.Name == name && v.DeviceId == deviceId); return(query.Count() != 0); }
public OmemoFingerprint getFingerprint(SignalProtocolAddress address, string accountId) { string chatId = ChatTable.generateId(address.getName(), accountId); string id = OmemoFingerprintTable.generateId(chatId, address); List <OmemoFingerprintTable> list = dB.Query <OmemoFingerprintTable>(true, "SELECT * FROM " + DBTableConsts.OMEMO_FINGERPRINT_TABLE + " WHERE id = ?;", id); return(list.Count <= 0 ? null : list[0].toOmemoFingerprint()); }
public void setSession(SignalProtocolAddress address, SessionRecord record, string accountId) { dB.InsertOrReplace(new SessionStoreTable() { id = SessionStoreTable.generateId(address, accountId), accountId = accountId, deviceId = address.getDeviceId(), name = address.getName(), session = record.serialize() }); }
public void StoreSession(SignalProtocolAddress address, SessionRecord record) { DeleteSession(address); // TODO: sqlite-net combined private keys for insertOrReplace var session = new Session() { DeviceId = address.getDeviceId(), Name = address.getName(), Record = record.serialize() }; conn.InsertOrReplace(session); return; }
private void requestBundleInformation() { setState(OmemoSessionBuildHelperState.REQUESTING_BUNDLE_INFORMATION); if (requestBundleInfoHelper != null) { requestBundleInfoHelper?.Dispose(); requestBundleInfoHelper = null; } requestBundleInfoHelper = new MessageResponseHelper <IQMessage>(CONNECTION, onRequestBundleInformationMessage, onTimeout); OmemoRequestBundleInformationMessage msg = new OmemoRequestBundleInformationMessage(FULL_ACCOUNT_JID, curAddress.getName(), curAddress.getDeviceId()); requestBundleInfoHelper.start(msg); }
public SessionRecord LoadSession(SignalProtocolAddress address) { var name = address.getName(); var deviceId = address.getDeviceId(); var query = conn.Table <Session>().Where(t => t.Name == name && t.DeviceId == deviceId); if (query != null && query.Any()) { return(new SessionRecord(query.First().Record)); } else { return(new SessionRecord()); } }
public void DeleteSession(SignalProtocolAddress address) { var name = address.getName(); var deviceId = address.getDeviceId(); var query = conn.Table <Session>().Delete(t => t.Name == name && t.DeviceId == deviceId); }
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); }
//--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- public static string generateId(SignalProtocolAddress address, string accountId) { return(address.getName() + "_" + address.getDeviceId() + "_" + accountId); }
public int CompareTo(object obj) { return(ADDRESS.getName().GetHashCode() ^ ADDRESS.getDeviceId().GetHashCode()); }
//--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- public static string generateId(string chatId, SignalProtocolAddress address) { return(generateId(chatId, address.getName(), address.getDeviceId())); }
public bool IsTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey) { return(IsTrustedIdentity(address.getName(), identityKey)); }
public bool SaveIdentity(SignalProtocolAddress address, IdentityKey identityKey) { return(SaveIdentity(address.getName(), identityKey)); }
public String serialize() { return(groupId + "::" + sender.getName() + "::" + sender.getDeviceId()); }
public void testBasicPreKeyV3() { SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore(); ECKeyPair bobPreKeyPair = Curve.generateKeyPair(); ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair(); byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobStore.GetIdentityKeyPair().getPrivateKey(), bobSignedPreKeyPair.getPublicKey().serialize()); PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31337, bobPreKeyPair.getPublicKey(), 22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, bobStore.GetIdentityKeyPair().getPublicKey()); aliceSessionBuilder.process(bobPreKey); Assert.IsTrue(aliceStore.ContainsSession(BOB_ADDRESS)); Assert.AreEqual((uint)3, aliceStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion()); String originalMessage = "L'homme est condamné à être libre"; SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.PREKEY_TYPE, outgoingMessage.getType()); PreKeySignalMessage incomingMessage = new PreKeySignalMessage(outgoingMessage.serialize()); bobStore.StorePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair)); bobStore.StoreSignedPreKey(22, new SignedPreKeyRecord(22, DateUtil.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature)); SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS); byte[] plaintext = bobSessionCipher.decrypt(incomingMessage, new BobDecryptionCallback(bobStore, originalMessage)); Assert.IsTrue(bobStore.ContainsSession(ALICE_ADDRESS)); Assert.AreEqual((uint)3, bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getSessionVersion()); Assert.IsNotNull(bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getAliceBaseKey()); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, bobOutgoingMessage.getType()); byte[] alicePlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobOutgoingMessage.serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(alicePlaintext)); runInteraction(aliceStore, bobStore); aliceStore = new TestInMemorySignalProtocolStore(); aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); bobPreKeyPair = Curve.generateKeyPair(); bobSignedPreKeyPair = Curve.generateKeyPair(); bobSignedPreKeySignature = Curve.calculateSignature(bobStore.GetIdentityKeyPair().getPrivateKey(), bobSignedPreKeyPair.getPublicKey().serialize()); bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31338, bobPreKeyPair.getPublicKey(), 23, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, bobStore.GetIdentityKeyPair().getPublicKey()); bobStore.StorePreKey(31338, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair)); bobStore.StoreSignedPreKey(23, new SignedPreKeyRecord(23, DateUtil.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature)); aliceSessionBuilder.process(bobPreKey); outgoingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); try { plaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(outgoingMessage.serialize())); throw new Exception("shouldn't be trusted!"); } catch (UntrustedIdentityException) { bobStore.SaveIdentity(ALICE_ADDRESS.getName(), new PreKeySignalMessage(outgoingMessage.serialize()).getIdentityKey()); } plaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(outgoingMessage.serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31337, Curve.generateKeyPair().getPublicKey(), 23, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, aliceStore.GetIdentityKeyPair().getPublicKey()); try { aliceSessionBuilder.process(bobPreKey); throw new Exception("shoulnd't be trusted!"); } catch (UntrustedIdentityException) { // good } }
private async Task buildSessionForDevicesAsync(Dictionary <uint, SessionCipher> sessions, IList <SignalProtocolAddress> devices) { if (devices.Count <= 0) { return; } SignalProtocolAddress device = devices[0]; devices.RemoveAt(0); // Validate the device fingerprint: OmemoFingerprint fingerprint = OMEMO_HELPER.OMEMO_STORE.LoadFingerprint(device); if (!(fingerprint is null) && !OMEMO_HELPER.OMEMO_STORE.IsFingerprintTrusted(fingerprint)) { Logger.Warn("[OmemoSessionBuildHelper] Not building a session with " + device.ToString() + " - key not trusted."); await buildSessionForDevicesAsync(sessions, devices); return; } // Check if there exists already a session for this device: if (OMEMO_HELPER.OMEMO_STORE.ContainsSession(device)) { // If yes, the load it: SessionCipher cipher = OMEMO_HELPER.loadCipher(device); sessions.Add(device.getDeviceId(), cipher); Logger.Info("[OmemoSessionBuildHelper] Session for " + device.ToString() + " loaded from cache."); } else { // Else try to build a new one by requesting the devices bundle information: OmemoBundleInformationResultMessage bundleMsg = await requestBundleInformationAsync(device); if (!(bundleMsg is null)) { OMEMO_HELPER.newSession(device.getName(), bundleMsg); // Validate fingerprints: if (fingerprint is null) { fingerprint = new OmemoFingerprint(bundleMsg.BUNDLE_INFO.PUBLIC_IDENTITY_KEY, device); OMEMO_HELPER.OMEMO_STORE.StoreFingerprint(fingerprint); } else { OmemoFingerprint receivedFingerprint = new OmemoFingerprint(bundleMsg.BUNDLE_INFO.PUBLIC_IDENTITY_KEY, device); // Make sure the fingerprint did not change or somebody is doing an attack: if (!fingerprint.checkIdentityKey(receivedFingerprint.IDENTITY_PUB_KEY)) { Logger.Warn("[OmemoSessionBuildHelper] Unable to establish session with " + device.ToString() + " - other fingerprint received than stored locally."); await buildSessionForDevicesAsync(sessions, devices); return; } } // Check if the fingerprint is trusted: if (OMEMO_HELPER.OMEMO_STORE.IsFingerprintTrusted(fingerprint)) { SessionCipher cipher = OMEMO_HELPER.loadCipher(device); sessions.Add(device.getDeviceId(), cipher); Logger.Info("[OmemoSessionBuildHelper] Session with " + device.ToString() + " established."); } else { Logger.Warn("[OmemoSessionBuildHelper] Unable to establish session with " + device.ToString() + " - key not trusted."); } }