public bool registerPreKeys(IdentityKey identityKey, PreKeyRecord lastResortKey, SignedPreKeyRecord signedPreKey, IList <PreKeyRecord> records) //throws IOException { List <PreKeyEntity> entities = new List <PreKeyEntity>(); foreach (PreKeyRecord record in records) { PreKeyEntity entity = new PreKeyEntity(record.getId(), record.getKeyPair().getPublicKey()); entities.Add(entity); } PreKeyEntity lastResortEntity = new PreKeyEntity(lastResortKey.getId(), lastResortKey.getKeyPair().getPublicKey()); SignedPreKeyEntity signedPreKeyEntity = new SignedPreKeyEntity(signedPreKey.getId(), signedPreKey.getKeyPair().getPublicKey(), signedPreKey.getSignature()); makeRequest(string.Format(PREKEY_PATH, ""), "PUT", JsonUtil.toJson(new PreKeyState(entities, lastResortEntity, signedPreKeyEntity, identityKey))); return(true); }
public bool setCurrentSignedPreKey(SignedPreKeyRecord signedPreKey)// throws IOException { SignedPreKeyEntity signedPreKeyEntity = new SignedPreKeyEntity(signedPreKey.getId(), signedPreKey.getKeyPair().getPublicKey(), signedPreKey.getSignature()); makeRequest(SIGNED_PREKEY_PATH, "PUT", JsonUtil.toJson(signedPreKeyEntity)); return(true); }
public OmemoBundleInformation getOmemoBundleInformation() { List <Tuple <uint, ECPublicKey> > pubPreKeys = new List <Tuple <uint, ECPublicKey> >(); foreach (PreKeyRecord key in omemoPreKeys) { pubPreKeys.Add(new Tuple <uint, ECPublicKey>(key.getId(), key.getKeyPair().getPublicKey())); } return(new OmemoBundleInformation(omemoIdentityKeyPair.getPublicKey(), omemoSignedPreKeyPair.getKeyPair().getPublicKey(), omemoSignedPreKeyId, omemoSignedPreKeyPair.getSignature(), pubPreKeys)); }
public async Task <bool> SetCurrentSignedPreKey(CancellationToken token, SignedPreKeyRecord signedPreKey)// throws IOException { SignedPreKeyEntity signedPreKeyEntity = new SignedPreKeyEntity(signedPreKey.getId(), signedPreKey.getKeyPair().getPublicKey(), signedPreKey.getSignature()); await MakeServiceRequestAsync(token, SIGNED_PREKEY_PATH, "PUT", JsonUtil.ToJson(signedPreKeyEntity)); return(true); }
public async Task <bool> RegisterPreKeys(CancellationToken token, IdentityKey identityKey, SignedPreKeyRecord signedPreKey, IList <PreKeyRecord> records) //throws IOException { List <PreKeyEntity> entities = new List <PreKeyEntity>(); foreach (PreKeyRecord record in records) { PreKeyEntity entity = new PreKeyEntity(record.getId(), record.getKeyPair().getPublicKey()); entities.Add(entity); } SignedPreKeyEntity signedPreKeyEntity = new SignedPreKeyEntity(signedPreKey.getId(), signedPreKey.getKeyPair().getPublicKey(), signedPreKey.getSignature()); await MakeServiceRequestAsync(token, string.Format(PREKEY_PATH, ""), "PUT", JsonUtil.ToJson(new PreKeyState(entities, signedPreKeyEntity, identityKey))); return(true); }
/// <summary> /// Generate the keysets for ourself /// </summary> /// <returns></returns> public bool sendSetPreKeys(bool isnew = false) { uint registrationId = 0; if (!isnew) { registrationId = (uint)this.GetLocalRegistrationId(); } else { registrationId = libaxolotl.util.KeyHelper.generateRegistrationId(true); } Random random = new Random(); uint randomid = (uint)libaxolotl.util.KeyHelper.getRandomSequence(5000);//65536 IdentityKeyPair identityKeyPair = libaxolotl.util.KeyHelper.generateIdentityKeyPair(); byte[] privateKey = identityKeyPair.getPrivateKey().serialize(); byte[] publicKey = identityKeyPair.getPublicKey().getPublicKey().serialize(); IList <PreKeyRecord> preKeys = libaxolotl.util.KeyHelper.generatePreKeys((uint)random.Next(), 200); SignedPreKeyRecord signedPreKey = libaxolotl.util.KeyHelper.generateSignedPreKey(identityKeyPair, randomid); PreKeyRecord lastResortKey = libaxolotl.util.KeyHelper.generateLastResortPreKey(); this.StorePreKeys(preKeys); this.StoreLocalData(registrationId, identityKeyPair.getPublicKey().serialize(), identityKeyPair.getPrivateKey().serialize()); this.StoreSignedPreKey(signedPreKey.getId(), signedPreKey); // FOR INTERNAL TESTING ONLY //this.InMemoryTestSetup(identityKeyPair, registrationId); ProtocolTreeNode[] preKeyNodes = new ProtocolTreeNode[200]; for (int i = 0; i < 200; i++) { byte[] prekeyId = adjustId(preKeys[i].getId().ToString()).Skip(1).ToArray(); byte[] prekey = preKeys[i].getKeyPair().getPublicKey().serialize().Skip(1).ToArray(); ProtocolTreeNode NodeId = new ProtocolTreeNode("id", null, null, prekeyId); ProtocolTreeNode NodeValue = new ProtocolTreeNode("value", null, null, prekey); preKeyNodes[i] = new ProtocolTreeNode("key", null, new ProtocolTreeNode[] { NodeId, NodeValue }, null); } ProtocolTreeNode registration = new ProtocolTreeNode("registration", null, null, adjustId(registrationId.ToString())); ProtocolTreeNode type = new ProtocolTreeNode("type", null, null, new byte[] { Curve.DJB_TYPE }); ProtocolTreeNode list = new ProtocolTreeNode("list", null, preKeyNodes, null); ProtocolTreeNode sid = new ProtocolTreeNode("id", null, null, adjustId(signedPreKey.getId().ToString(), true)); ProtocolTreeNode identity = new ProtocolTreeNode("identity", null, null, identityKeyPair.getPublicKey().getPublicKey().serialize().Skip(1).ToArray()); ProtocolTreeNode value = new ProtocolTreeNode("value", null, null, signedPreKey.getKeyPair().getPublicKey().serialize().Skip(1).ToArray()); ProtocolTreeNode signature = new ProtocolTreeNode("signature", null, null, signedPreKey.getSignature()); ProtocolTreeNode secretKey = new ProtocolTreeNode("skey", null, new ProtocolTreeNode[] { sid, value, signature }, null); String id = TicketManager.GenerateId(); Helper.DebugAdapter.Instance.fireOnPrintDebug(string.Format("axolotl id = {0}", id)); ProtocolTreeNode Node = new ProtocolTreeNode("iq", new KeyValue[] { new KeyValue("id", id), new KeyValue("to", "s.whatsapp.net"), new KeyValue("type", "set"), new KeyValue("xmlns", "encrypt") }, new ProtocolTreeNode[] { identity, registration, type, list, secretKey }, null); this.SendNode(Node); return(true); }
public string getBundleInfoMsg(IdentityKeyPair identKey, SignedPreKeyRecord signedPreKey, IList <PreKeyRecord> preKeys) { IList <Tuple <uint, ECPublicKey> > publicPreKeys = new List <Tuple <uint, ECPublicKey> >(); foreach (PreKeyRecord pk in preKeys) { publicPreKeys.Add(new Tuple <uint, ECPublicKey>(pk.getId(), pk.getKeyPair().getPublicKey())); } OmemoBundleInformation bundleInfo = new OmemoBundleInformation(identKey.getPublicKey(), signedPreKey.getKeyPair().getPublicKey(), signedPreKey.getId(), signedPreKey.getSignature(), publicPreKeys); StringBuilder sb = new StringBuilder("<iq xml:lang='en' to='"); sb.Append(ALICE_ADDRESS.getName()); sb.Append("/SOME_RESOURCE' from='"); sb.Append(BOB_ADDRESS.getName()); sb.Append("' type='result' id='83d5aa79-484b-4b76-83db-703f5cf60b57'><pubsub xmlns='http://jabber.org/protocol/pubsub'><items node='eu.siacs.conversations.axolotl.bundles:"); sb.Append(BOB_ADDRESS.getDeviceId()); sb.Append("'>"); sb.Append(bundleInfo.toXElement(Consts.XML_XEP_0384_BUNDLE_INFO_NODE + BOB_ADDRESS.getDeviceId())); sb.Append("</items></pubsub></iq>"); return(sb.ToString()); }
public void Test_OmemoBundleInformation_2() { IdentityKeyPair aliceIdentKey = CryptoUtils.generateOmemoIdentityKeyPair(); IList <PreKeyRecord> alicePreKeys = CryptoUtils.generateOmemoPreKeys(); SignedPreKeyRecord aliceSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(aliceIdentKey); string bundleInfo = getBundleInfoMsg(aliceIdentKey, aliceSignedPreKey, alicePreKeys); MessageParser2 parser = new MessageParser2(); List <AbstractMessage> messages = parser.parseMessages(ref bundleInfo); // Check if message parsed successfully: Assert.IsTrue(messages.Count == 1); Assert.IsInstanceOfType(messages[0], typeof(OmemoBundleInformationResultMessage)); OmemoBundleInformationResultMessage bundleInfoMsg = messages[0] as OmemoBundleInformationResultMessage; // Check if keys match: Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.PUBLIC_IDENTITY_KEY.serialize().SequenceEqual(aliceIdentKey.getPublicKey().serialize())); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.PUBLIC_SIGNED_PRE_KEY.serialize().SequenceEqual(aliceSignedPreKey.getKeyPair().getPublicKey().serialize())); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.SIGNED_PRE_KEY_ID == aliceSignedPreKey.getId()); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.SIGNED_PRE_KEY_SIGNATURE.SequenceEqual(aliceSignedPreKey.getSignature())); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.PUBLIC_PRE_KEYS.Count == alicePreKeys.Count); foreach (PreKeyRecord key in alicePreKeys) { IEnumerable <Tuple <uint, ECPublicKey> > matches = bundleInfoMsg.BUNDLE_INFO.PUBLIC_PRE_KEYS.Where(x => x.Item1 == key.getId()); Assert.IsTrue(matches.Count() == 1); byte[] a = matches.First().Item2.serialize(); byte[] b = key.getKeyPair().getPublicKey().serialize(); Assert.IsTrue(a.SequenceEqual(b)); } }
public void Test_OmemoBundleInformation_1() { IdentityKeyPair aliceIdentKey = CryptoUtils.generateOmemoIdentityKeyPair(); IList <PreKeyRecord> alicePreKeys = KeyHelper.generatePreKeys(0, 1); SignedPreKeyRecord aliceSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(aliceIdentKey); string bundleInfo = getBundleInfoMsg(aliceIdentKey, aliceSignedPreKey, alicePreKeys); MessageParser2 parser = new MessageParser2(); List <AbstractMessage> messages = parser.parseMessages(ref bundleInfo); // Check if message parsed successfully: Assert.IsTrue(messages.Count == 1); Assert.IsInstanceOfType(messages[0], typeof(OmemoBundleInformationResultMessage)); OmemoBundleInformationResultMessage bundleInfoMsg = messages[0] as OmemoBundleInformationResultMessage; // Check if keys match: Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.PUBLIC_IDENTITY_KEY.serialize().SequenceEqual(aliceIdentKey.getPublicKey().serialize())); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.PUBLIC_SIGNED_PRE_KEY.serialize().SequenceEqual(aliceSignedPreKey.getKeyPair().getPublicKey().serialize())); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.SIGNED_PRE_KEY_ID == aliceSignedPreKey.getId()); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.SIGNED_PRE_KEY_SIGNATURE.SequenceEqual(aliceSignedPreKey.getSignature())); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.PUBLIC_PRE_KEYS.Count == 1); Assert.IsTrue(bundleInfoMsg.BUNDLE_INFO.PUBLIC_PRE_KEYS[0].Item2.serialize().SequenceEqual(alicePreKeys[0].getKeyPair().getPublicKey().serialize())); }
public void Test_Libsignal_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(); // Alice builds a session to Bob: SessionBuilder sessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS); PreKeyBundle bobPreKey = new PreKeyBundle(BOB_ADDRESS.getDeviceId(), BOB_ADDRESS.getDeviceId(), bobPreKeys[0].getId(), bobPreKeys[0].getKeyPair().getPublicKey(), bobSignedPreKey.getId(), bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentKey.getPublicKey()); 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 .)"; SessionCipher aliceSessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS); CiphertextMessage aliceOutMsg = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(aliceOrigMsg)); // Check if successfully encrypted: Assert.IsTrue(aliceOutMsg.getType() == CiphertextMessage.PREKEY_TYPE); // Bob receives the message: PreKeySignalMessage bobInMsg = new PreKeySignalMessage(aliceOutMsg.serialize()); SessionCipher bobSessionCipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, ALICE_ADDRESS); byte[] bobData = bobSessionCipher.decrypt(bobInMsg); string bobRecMsg = Encoding.UTF8.GetString(bobData); // Check if successfully send: Assert.AreEqual(aliceOrigMsg, bobRecMsg); Assert.IsTrue(bobSessionStore.ContainsSession(ALICE_ADDRESS)); //---------------------------Connection/App get restarted:--------------------------- // Bob answers: string bobOrigMsg = ":(){ :|:& };:"; // Simulate a chat break: bobSessionCipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, ALICE_ADDRESS); CiphertextMessage bobOutMsg = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(bobOrigMsg)); // Alice receives the message: aliceSessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS); SignalMessage aliceInMsg = new SignalMessage(bobOutMsg.serialize()); byte[] aliceData = aliceSessionCipher.decrypt(aliceInMsg); string aliceRecMsg = Encoding.UTF8.GetString(aliceData); // Check if successfully send: Assert.AreEqual(bobOrigMsg, aliceRecMsg); Assert.IsTrue(bobSessionStore.ContainsSession(ALICE_ADDRESS)); }
private void RequestRegister(uint registrationId, IdentityKeyPair identityKeyPair, SignedPreKeyRecord signedPreKey, List <PreKeyRecord> preKeys) { //Send the login username and password to the server and get response string apiUrl = "https://ycandgap.me/api_server2.php"; string apiMethod = "registerUser"; // Login_Request has two properties: username and password Login_Request myLogin_Request = new Login_Request(); myLogin_Request.Username = username.Text; myLogin_Request.Password = password.Text.GetHashCode(); myLogin_Request.RegistrationID = registrationId; myLogin_Request.PublicIdentityKey = JsonConvert.SerializeObject(identityKeyPair.getPublicKey().serialize()); myLogin_Request.PublicSignedPreKeyID = signedPreKey.getId(); myLogin_Request.PublicSignedPreKeySignature = JsonConvert.SerializeObject(signedPreKey.getSignature()); myLogin_Request.PublicSignedPreKey = JsonConvert.SerializeObject(signedPreKey.getKeyPair().getPublicKey().serialize()); // Save in local Database ISharedPreferences sharedprefs = PreferenceManager.GetDefaultSharedPreferences(this); ISharedPreferencesEditor editor = sharedprefs.Edit(); // Store identityKeyPair somewhere durable and safe. editor.PutString("IdentityKeyPair", JsonConvert.SerializeObject(identityKeyPair.serialize())); editor.PutString("SignedPreKey", JsonConvert.SerializeObject(signedPreKey.serialize())); editor.PutString("Username", username.Text); editor.PutInt("Password", password.Text.GetHashCode()); // Store registrationId somewhere durable and safe. editor.PutString("RegistrationId", registrationId.ToString()); editor.Apply(); // make http post request string response = Http.Post(apiUrl, new NameValueCollection() { { "api_method", apiMethod }, { "api_data", JsonConvert.SerializeObject(myLogin_Request) } }); // decode json string to dto object API_Response r = JsonConvert.DeserializeObject <API_Response>(response); if (r != null) { if (!r.IsError) { foreach (PreKeyRecord preKey in preKeys) { Prekey_Request preKey_Request = new Prekey_Request(); preKey_Request.PublicSignedPreKeyID = signedPreKey.getId(); preKey_Request.PublicPreKeyID = preKey.getId(); preKey_Request.PublicPreKey = JsonConvert.SerializeObject(preKey.getKeyPair().getPublicKey().serialize()); apiMethod = "storePreKeys"; // make http post request string preKeyResponse = Http.Post(apiUrl, new NameValueCollection() { { "api_method", apiMethod }, { "api_data", JsonConvert.SerializeObject(preKey_Request) } }); // decode json string to dto object API_Response preKeyR = JsonConvert.DeserializeObject <API_Response>(preKeyResponse); if (preKeyR == null) { break; } } } } }
private void InitializeSessions(TestInMemorySignalProtocolStore aliceStore, TestInMemorySignalProtocolStore bobStore) { ECKeyPair bobPreKey = Curve.generateKeyPair(); IdentityKeyPair bobIdentityKey = bobStore.GetIdentityKeyPair(); SignedPreKeyRecord bobSignedPreKey = KeyHelper.generateSignedPreKey(bobIdentityKey, 2); PreKeyBundle bobBundle = new PreKeyBundle(1, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey()); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, new SignalProtocolAddress("+14152222222", 1)); aliceSessionBuilder.process(bobBundle); bobStore.StoreSignedPreKey(2, bobSignedPreKey); bobStore.StorePreKey(1, new PreKeyRecord(1, bobPreKey)); }