public function processResponse($keyExchangeMessage) { $sessionRecord = $this->sessionStore->loadSession($this->recipientId, $this->deviceId); $sessionState = $sessionRecord->getSessionState(); $hasPendingKeyExchange = $sessionState->hasPendingKeyExchange(); $isSimultaneousInitiateResponse = $keyExchangeMessage->isResponseForSimultaneousInitiate(); if (!$hasPendingKeyExchange || $sessionState->getPendingKeyExchangeSequence() != $keyExchangeMessage->getSequence()) { Log::warn('procResponse', 'No matching sequence for response. Is simultaneous initiate response:' . ($isSimultaneousInitiateResponse ? 'true' : 'false')); if (!$isSimultaneousInitiateResponse) { throw new StaleKeyExchangeException(); } else { return; } } $parameters = new SymmetricBuilder(); $parameters->setOurBaseKey($sessionRecord->getSessionState()->getPendingKeyExchangeBaseKey())->setOurRatchetKey($sessionRecord->getSessionState()->getPendingKeyExchangeRatchetKey())->setOurIdentityKey($sessionRecord->getSessionState()->getPendingKeyExchangeIdentityKey())->setTheirBaseKey($keyExchangeMessage->getBaseKey())->setTheirRatchetKey($keyExchangeMessage->getRatchetKey())->setTheirIdentityKey($keyExchangeMessage->getIdentityKey()); if (!$sessionRecord->isFresh()) { $sessionRecord->archiveCurrentState(); } RatchetingSession::initializeSession($sessionRecord->getSessionState(), min($keyExchangeMessage->getMaxVersion(), CiphertextMessage::CURRENT_VERSION), $parameters->create()); if ($sessionRecord->getSessionState()->getSessionVersion() >= 3 && !Curve::verifySignature($keyExchangeMessage->getIdentityKey()->getPublicKey(), $keyExchangeMessage->getBaseKey()->serialize(), $keyExchangeMessage->getBaseKeySignature())) { throw new InvalidKeyException("Base key signature doesn't match!"); } $this->sessionStore->storeSession($this->recipientId, $this->deviceId, $sessionRecord); $this->identityKeyStore->saveIdentity($this->recipientId, $keyExchangeMessage->getIdentityKey()); }
protected function initializeSessionsV3($aliceSessionState, $bobSessionState) { $aliceIdentityKeyPair = Curve::generateKeyPair(); $aliceIdentityKey = new IdentityKeyPair(new IdentityKey($aliceIdentityKeyPair->getPublicKey()), $aliceIdentityKeyPair->getPrivateKey()); $aliceBaseKey = Curve::generateKeyPair(); $aliceEphemeralKey = Curve::generateKeyPair(); $alicePreKey = $aliceBaseKey; $bobIdentityKeyPair = Curve::generateKeyPair(); $bobIdentityKey = new IdentityKeyPair(new IdentityKey($bobIdentityKeyPair->getPublicKey()), $bobIdentityKeyPair->getPrivateKey()); $bobBaseKey = Curve::generateKeyPair(); $bobEphemeralKey = $bobBaseKey; $bobPreKey = Curve::generateKeyPair(); $aliceParameters = AliceAxolotlParameters::newBuilder()->setOurBaseKey($aliceBaseKey)->setOurIdentityKey($aliceIdentityKey)->setTheirOneTimePreKey(null)->setTheirRatchetKey($bobEphemeralKey->getPublicKey())->setTheirSignedPreKey($bobBaseKey->getPublicKey())->setTheirIdentityKey($bobIdentityKey->getPublicKey())->create(); $bobParameters = BobAxolotlParameters::newBuilder()->setOurRatchetKey($bobEphemeralKey)->setOurSignedPreKey($bobBaseKey)->setOurOneTimePreKey(null)->setOurIdentityKey($bobIdentityKey)->setTheirIdentityKey($aliceIdentityKey->getPublicKey())->setTheirBaseKey($aliceBaseKey->getPublicKey())->create(); RatchetingSession::initializeSessionAsAlice($aliceSessionState, 3, $aliceParameters); RatchetingSession::initializeSessionAsBob($bobSessionState, 3, $bobParameters); }