KeyExchangeMessage::KeyExchangeMessage(int messageVersion, int sequence, int flags, const DjbECPublicKey &baseKey, const QByteArray &baseKeySignature, const DjbECPublicKey &ratchetKey, const IdentityKey &identityKey) { this->supportedVersion = CiphertextMessage::CURRENT_VERSION; this->version = messageVersion; this->sequence = sequence; this->flags = flags; this->baseKey = baseKey; this->baseKeySignature = baseKeySignature; this->ratchetKey = ratchetKey; this->identityKey = identityKey; textsecure::KeyExchangeMessage message; message.set_id((sequence << 5) | flags); message.set_basekey(baseKey.serialize().constData()); message.set_ratchetkey(ratchetKey.serialize().constData()); message.set_identitykey(identityKey.serialize().constData()); if (messageVersion >= 3) { message.set_basekeysignature(baseKeySignature.constData()); } ::std::string serializedMessage = message.SerializeAsString(); this->serialized = QByteArray(serializedMessage.data(), serializedMessage.length()); this->serialized.prepend(ByteUtil::intsToByteHighAndLow(this->version, this->supportedVersion)); }
SenderKeyState::SenderKeyState(int id, int iteration, const ByteArray &chainKey, const DjbECPublicKey &signatureKeyPublic, const DjbECPrivateKey &signatureKeyPrivate) { senderKeyStateStructure = textsecure::SenderKeyStateStructure(); senderKeyStateStructure.set_senderkeyid(id); senderKeyStateStructure.mutable_senderchainkey()->set_iteration(iteration); senderKeyStateStructure.mutable_senderchainkey()->set_seed(chainKey.c_str(), chainKey.size()); senderKeyStateStructure.mutable_sendersigningkey()->set_public_(signatureKeyPublic.serialize().c_str(), signatureKeyPublic.serialize().size()); senderKeyStateStructure.mutable_sendersigningkey()->set_private_(signatureKeyPrivate.serialize().c_str(), signatureKeyPrivate.serialize().size()); /*textsecure::SenderKeyStateStructure::SenderChainKey senderChainKeyStructure; senderChainKeyStructure.set_iteration(iteration); senderChainKeyStructure.set_seed(chainKey.c_str()); textsecure::SenderKeyStateStructure::SenderSigningKey signingKeyStructure; signingKeyStructure.set_public_(signatureKeyPublic.serialize().c_str()); signingKeyStructure.set_private_(signatureKeyPrivate.serialize().c_str()); senderKeyStateStructure = textsecure::SenderKeyStateStructure(); senderKeyStateStructure.set_senderkeyid(id); senderKeyStateStructure.mutable_senderchainkey()->CopyFrom(senderChainKeyStructure); senderKeyStateStructure.mutable_sendersigningkey()->CopyFrom(signingKeyStructure);*/ }
void SessionBuilder::process(const PreKeyBundle &preKey) { if (!identityKeyStore->isTrustedIdentity(recipientId, preKey.getIdentityKey())) { throw UntrustedIdentityException(QString("Untrusted identity: %1").arg(recipientId)); } if (!preKey.getSignedPreKey().serialize().isEmpty() && !Curve::verifySignature(preKey.getSignedPreKey(), preKey.getIdentityKey().getPublicKey().serialize(), preKey.getSignedPreKeySignature())) { qWarning() << preKey.getIdentityKey().getPublicKey().serialize().toHex(); qWarning() << preKey.getSignedPreKey().serialize().toHex(); qWarning() << preKey.getSignedPreKeySignature().toHex(); throw InvalidKeyException("Invalid signature on device key!"); } if (preKey.getSignedPreKey().serialize().isEmpty() && preKey.getPreKey().serialize().isEmpty()) { throw InvalidKeyException("Both signed and unsigned prekeys are absent!"); } bool supportsV3 = !preKey.getSignedPreKey().serialize().isEmpty(); SessionRecord *sessionRecord = sessionStore->loadSession(recipientId, deviceId); ECKeyPair ourBaseKey = Curve::generateKeyPair(); DjbECPublicKey theirSignedPreKey = supportsV3 ? preKey.getSignedPreKey() : preKey.getPreKey(); DjbECPublicKey theirOneTimePreKey = preKey.getPreKey(); int theirOneTimePreKeyId = theirOneTimePreKey.serialize().isEmpty() ? -1 : preKey.getPreKeyId(); AliceAxolotlParameters parameters; parameters.setOurBaseKey(ourBaseKey); parameters.setOurIdentityKey(identityKeyStore->getIdentityKeyPair()); parameters.setTheirIdentityKey(preKey.getIdentityKey()); parameters.setTheirSignedPreKey(theirSignedPreKey); parameters.setTheirRatchetKey(theirSignedPreKey); if (supportsV3) { parameters.setTheirOneTimePreKey(theirOneTimePreKey); } if (!sessionRecord->isFresh()) sessionRecord->archiveCurrentState(); RatchetingSession::initializeSession(sessionRecord->getSessionState(), supportsV3 ? 3 : 2, parameters); sessionRecord->getSessionState()->setUnacknowledgedPreKeyMessage(theirOneTimePreKeyId, preKey.getSignedPreKeyId(), ourBaseKey.getPublicKey()); sessionRecord->getSessionState()->setLocalRegistrationId(identityKeyStore->getLocalRegistrationId()); sessionRecord->getSessionState()->setRemoteRegistrationId(preKey.getRegistrationId()); sessionRecord->getSessionState()->setAliceBaseKey(ourBaseKey.getPublicKey().serialize()); sessionStore->storeSession(recipientId, deviceId, sessionRecord); identityKeyStore->saveIdentity(recipientId, preKey.getIdentityKey()); }
PreKeyWhisperMessage::PreKeyWhisperMessage(int messageVersion, ulong registrationId, ulong preKeyId, ulong signedPreKeyId, const DjbECPublicKey &baseKey, const IdentityKey &identityKey, QSharedPointer<WhisperMessage> message) { this->version = messageVersion; this->registrationId = registrationId; this->preKeyId = preKeyId; this->signedPreKeyId = signedPreKeyId; this->baseKey = baseKey; this->identityKey = identityKey; this->message = message; textsecure::PreKeyWhisperMessage preKeyWhisperMessage; preKeyWhisperMessage.set_signedprekeyid(signedPreKeyId); QByteArray basekey = baseKey.serialize(); preKeyWhisperMessage.set_basekey(basekey.constData(), basekey.size()); QByteArray identitykey = identityKey.serialize(); preKeyWhisperMessage.set_identitykey(identitykey.constData(), identitykey.size()); QByteArray bytemessage = message->serialize(); preKeyWhisperMessage.set_message(bytemessage.constData(), bytemessage.size()); preKeyWhisperMessage.set_registrationid(registrationId); if (preKeyId >= 0) { preKeyWhisperMessage.set_prekeyid(preKeyId); } ::std::string serializedmessage = preKeyWhisperMessage.SerializeAsString(); QByteArray messageBytes = QByteArray(serializedmessage.data(), serializedmessage.length()); this->serialized = messageBytes; this->serialized.prepend(ByteUtil::intsToByteHighAndLow(this->version, CURRENT_VERSION)); }
WhisperMessage::WhisperMessage(int messageVersion, const QByteArray &macKey, const DjbECPublicKey &senderRatchetKey, uint counter, uint previousCounter, const QByteArray &ciphertext, const IdentityKey &senderIdentityKey, const IdentityKey &receiverIdentityKey) { textsecure::WhisperMessage whisperMessage; QByteArray ratchetKey = senderRatchetKey.serialize(); whisperMessage.set_ratchetkey(ratchetKey.constData(), ratchetKey.size()); whisperMessage.set_counter(counter); whisperMessage.set_previouscounter(previousCounter); whisperMessage.set_ciphertext(ciphertext.constData() ,ciphertext.size()); ::std::string serializedMessage = whisperMessage.SerializeAsString(); QByteArray message = QByteArray(serializedMessage.data(), serializedMessage.length()); message.prepend(ByteUtil::intsToByteHighAndLow(messageVersion, CURRENT_VERSION)); QByteArray mac = getMac(messageVersion, senderIdentityKey, receiverIdentityKey, macKey, message); this->serialized = message; this->serialized.append(mac); this->senderRatchetKey = senderRatchetKey; this->counter = counter; this->previousCounter = previousCounter; this->ciphertext = ciphertext; this->messageVersion = messageVersion; }