public function sendSetPreKeys($new = false) { $axolotl = new KeyHelper(); $identityKeyPair = $axolotl->generateIdentityKeyPair(); $privateKey = $identityKeyPair->getPrivateKey()->serialize(); $publicKey = $identityKeyPair->getPublicKey()->serialize(); $keys = $axolotl->generatePreKeys(mt_rand(), 200); $this->axolotlStore->storePreKeys($keys); for ($i = 0; $i < 200; $i++) { $prekeyId = adjustId($keys[$i]->getId()); $prekey = substr($keys[$i]->getKeyPair()->getPublicKey()->serialize(), 1); $id = new ProtocolNode('id', null, null, $prekeyId); $value = new ProtocolNode('value', null, null, $prekey); $prekeys[] = new ProtocolNode('key', null, array($id, $value), null); // 200 PreKeys } if ($new) { $registrationId = $this->axolotlStore->getLocalRegistrationId(); } else { $registrationId = $axolotl->generateRegistrationId(); } $registration = new ProtocolNode('registration', null, null, adjustId($registrationId)); $identity = new ProtocolNode('identity', null, null, substr($publicKey, 1)); $type = new ProtocolNode('type', null, null, chr(Curve::DJB_TYPE)); $this->axolotlStore->storeLocalData($registrationId, $identityKeyPair); $list = new ProtocolNode('list', null, $prekeys, null); $signedRecord = $axolotl->generateSignedPreKey($identityKeyPair, $axolotl->getRandomSequence(65536)); $this->axolotlStore->storeSignedPreKey($signedRecord->getId(), $signedRecord); $sid = new ProtocolNode('id', null, null, adjustId($signedRecord->getId())); $value = new ProtocolNode('value', null, null, substr($signedRecord->getKeyPair()->getPublicKey()->serialize(), 1)); $signature = new ProtocolNode('signature', null, null, $signedRecord->getSignature()); $secretKey = new ProtocolNode('skey', null, array($sid, $value, $signature), null); $iqId = $this->createIqId(); $iqNode = new ProtocolNode('iq', array("id" => $iqId, "to" => Constants::WHATSAPP_SERVER, "type" => "set", "xmlns" => "encrypt"), array($identity, $registration, $type, $list, $secretKey), null); $this->sendNode($iqNode); $this->waitForServer($iqId); }
public function test_basicEncryptDecrypt() { $aliceStore = new InMemorySenderKeyStore(); $bobStore = new InMemorySenderKeyStore(); $charlieStore = new InMemorySenderKeyStore(); $aliceSessionBuilder = new GroupSessionBuilder($aliceStore); $bobSessionBuilder = new GroupSessionBuilder($bobStore); $charlieSessionBuilder = new GroupSessionBuilder($charlieStore); $aliceGroupCipher = new GroupCipher($aliceStore, "groupWithBobInIt"); $bobGroupCipher = new GroupCipher($bobStore, "groupWithBobInIt::aliceUserName"); $charlieGroupCipher = new GroupCipher($charlieStore, "groupWithBobInIt::aliceUserName"); $aliceSenderKey = KeyHelper::generateSenderKey(); $aliceSenderSigningKey = KeyHelper::generateSenderSigningKey(); $aliceSenderKeyId = KeyHelper::generateSenderKeyId(); $aliceDistributionMessage = $aliceSessionBuilder->process("groupWithBobInIt", $aliceSenderKeyId, 0, $aliceSenderKey, $aliceSenderSigningKey); echo niceVarDump($aliceDistributionMessage); echo niceVarDump($aliceDistributionMessage->serialize()); echo $aliceDistributionMessage->serialize(); $bobSessionBuilder->processSender("groupWithBobInIt::aliceUserName", $aliceDistributionMessage); $ciphertextFromAlice = $aliceGroupCipher->encrypt("smert ze smert"); $plaintextFromAlice_Bob = $bobGroupCipher->decrypt($ciphertextFromAlice); $ciphertextFromAlice_2 = $aliceGroupCipher->encrypt("smert ze smert"); echo niceVarDump($aliceDistributionMessage); $charlieSessionBuilder->processSender("groupWithBobInIt::aliceUserName", $aliceDistributionMessage); $plaintextFromAlice_Charlie = $charlieGroupCipher->decrypt($ciphertextFromAlice_2); $this->assertEquals($plaintextFromAlice_Bob, "smert ze smert"); $this->assertEquals($plaintextFromAlice_Charlie, "smert ze smert"); }
public function InMemoryIdentityKeyStore() { $this->trustedKeys = []; $identityKeyPairKeys = Curve::generateKeyPair(); $this->identityKeyPair = new IdentityKeyPair(new IdentityKey($identityKeyPairKeys->getPublicKey()), $identityKeyPairKeys->getPrivateKey()); $this->localRegistrationId = KeyHelper::generateRegistrationId(); }
public function processInitKeyExchangeMessage() { try { $sequence = KeyHelper::getRandomSequence(65534) + 1; $flags = KeyExchangeMessage::INITIATE_FLAG; $baseKey = Curve::generateKeyPair(); $ratchetKey = Curve::generateKeyPair(); $identityKey = $this->identityKeyStore->getIdentityKeyPair(); $baseKeySignature = Curve::calculateSignature($identityKey->getPrivateKey(), $baseKey->getPublicKey()->serialize()); $sessionRecord = $this->sessionStore->loadSession($this->recipientId, $this->deviceId); $sessionRecord->getSessionState()->setPendingKeyExchange($sequence, $baseKey, $ratchetKey, $identityKey); $this->sessionStore->storeSession($this->recipientId, $this->deviceId, $sessionRecord); return new KeyExchangeMessage(2, $sequence, $flags, $baseKey->getPublicKey(), $baseKeySignature, $ratchetKey->getPublicKey(), $identityKey->getPublicKey()); } catch (InvalidKeyException $ex) { throw new Exception($ex->getMessage()); } }