Esempio n. 1
0
 public function KeyExchangeMessage($messageVersion = null, $sequence = null, $flags = null, $baseKey = null, $baseKeySignature = null, $ratchetKey = null, $identityKey = null, $serialized = null)
 {
     /*
     :type messageVersion: int
     :type  sequence: int
     :type flags:int
     :type baseKey: ECPublicKey
     :type baseKeySignature: bytearray
     :type ratchetKey: ECPublicKey
     :type identityKey: IdentityKey
     :type serialized: bytearray
     */
     if ($serialized == null) {
         $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;
         $version = ByteUtil::intsToByteHighAndLow($this->version, $this->supportedVersion);
         $keyExchangeMessage = new Textsecure_KeyExchangeMessage();
         $keyExchangeMessage->setId($this->sequence << 5 | $this->flags);
         $keyExchangeMessage->setBaseKey($baseKey->serialize());
         $keyExchangeMessage->setRatchetKey($ratchetKey->serialize());
         $keyExchangeMessage->setIdentityKey($identityKey->serialize());
         if ($messageVersion >= 3) {
             $keyExchangeMessage->setBaseKeySignature($baseKeySignature);
         }
         $this->serialized = ByteUtil::combine([chr((int) $version), $keyExchangeMessage->serializeToString()]);
     } else {
         try {
             $parts = ByteUtil::split($serialized, 1, strlen($serialized) - 1);
             $this->version = ByteUtil::highBitsToInt(ord($parts[0][0]));
             $this->supportedVersion = ByteUtil::lowBitsToInt(ord($parts[0][0]));
             if ($this->version <= CiphertextMessage::UNSUPPORTED_VERSION) {
                 throw new LegacyMessageException('Unsupported legacy version: ' . $this->version);
             }
             if ($this->version > CiphertextMessage::CURRENT_VERSION) {
                 throw new InvalidVersionException('Unkown version: ' . $this->version);
             }
             $message = new Textsecure_KeyExchangeMessage();
             $message->parseFromString($parts[1]);
             if ($message->getId() == null || $message->getBaseKey() == null || $message->getRatchetKey() == null || $message->getIdentityKey() == null || $this->version >= 3 && $message->getBaseKeySignature() == null) {
                 throw new InvalidMessageException('Some required fields are missing!');
             }
             $this->sequence = $message->getId() >> 5;
             $this->flags = $message->getId() & 0x1f;
             $this->serialized = $serialized;
             $this->baseKey = Curve::decodePoint($message->getBaseKey(), 0);
             $this->baseKeySignature = $message->getBaseKeySignature();
             $this->ratchetKey = Curve::decodePoint($message->getRatchetKey(), 0);
             $this->identityKey = new IdentityKey($message->getIdentityKey(), 0);
         } catch (InvalidKeyException $ex) {
             throw new InvalidMessageException($ex->getMessage());
         }
     }
 }
 public function DerivedMessageSecrets($okm)
 {
     $keys = ByteUtil::split($okm, self::CIPHER_KEY_LENGTH, self::MAC_KEY_LENGTH, self::IV_LENGTH);
     $this->cipherKey = $keys[0];
     //AES
     $this->macKey = $keys[1];
     //sha256
     $this->iv = $keys[2];
 }
Esempio n. 3
0
 public function SenderMessageKey($iteration, $seed)
 {
     $hkdf = new HKDFv3();
     $derivative = $hkdf->deriveSecrets($seed, "WhisperGroup", 48);
     /* match: 21c8b6ca */
     $parts = ByteUtil::split($derivative, 16, 32);
     $this->iteration = $iteration;
     $this->seed = $seed;
     $this->iv = $parts[0];
     $this->cipherKey = $parts[1];
 }
Esempio n. 4
0
 public function verifySignature($signatureKey)
 {
     try {
         $parts = ByteUtil::split($this->serialized, strlen($this->serialized) - self::SIGNATURE_LENGTH, self::SIGNATURE_LENGTH);
         if (!Curve::verifySignature($signatureKey, $parts[0], $parts[1])) {
             throw new InvalidMessageException("Invalid signature!");
         }
     } catch (InvalidKeyException $ex) {
         throw new InvalidMessageException($ex->getMessage());
     }
 }
 public function SenderKeyDistributionMessage($id = null, $iteration = null, $chainKey = null, $signatureKey = null, $serialized = null)
 {
     if ($serialized == null) {
         $version = ByteUtil::intsToByteHighAndLow(self::CURRENT_VERSION, self::CURRENT_VERSION);
         $this->id = $id;
         $this->iteration = $iteration;
         $this->chainKey = $chainKey;
         $this->signatureKey = $signatureKey;
         $proto_skdm = new Textsecure_SenderKeyDistributionMessage();
         $proto_skdm->setId($id);
         $proto_skdm->setIteration($iteration);
         $proto_skdm->setChainKey((string) $chainKey);
         $proto_skdm->setSigningKey((string) $signatureKey->serialize());
         $this->serialized = chr($version) . $proto_skdm->serializeToString();
     } else {
         $parts = ByteUtil::split($serialized, 1, strlen($serialized) - 1);
         $version = ord($parts[0][0]);
         $message = $parts[1];
         if (ByteUtil::highBitsToInt($version) < self::CURRENT_VERSION) {
             throw new LegacyMessageException("Legacy message: " + ByteUtil::highBitsToInt($version));
         }
         if (ByteUtil::highBitsToInt($version) > self::CURRENT_VERSION) {
             throw new InvalidMessageException("Unknown version: " + ByteUtil::highBitsToInt($version));
         }
         $proto_skdm = new Textsecure_SenderKeyDistributionMessage();
         try {
             $proto_skdm->parseFromString($message);
         } catch (Exception $ex) {
             throw new InvalidMessageException("Incomplete message.");
         }
         if ($proto_skdm->getId() === null || $proto_skdm->getIteration() === null || $proto_skdm->getChainKey() === null || $proto_skdm->getSigningKey() === null) {
             throw new InvalidMessageException("Incomplete message.");
         }
         $this->serialized = $serialized;
         $this->id = $proto_skdm->getId();
         $this->iteration = $proto_skdm->getIteration();
         $this->chainKey = $proto_skdm->getChainKey();
         $this->signatureKey = Curve::decodePoint($proto_skdm->getSigningKey(), 0);
     }
 }
Esempio n. 6
0
 public function testSplit()
 {
     $okm = pack('H*', '02a9aa6c7dbd64f9d3aa92f92a277bf54609dadf0b00828acfc61e3c724b84a7bfbe5efb603030526742e3ee89c7024e884e' . '440f1ff376bb2317b2d64deb7c8322f4c5015d9d895849411ba1d793a827');
     $data = '';
     for ($i = 0; $i < 80; $i++) {
         $data .= chr($i);
     }
     $a_data = '';
     for ($i = 0; $i < 32; $i++) {
         $a_data .= chr($i);
     }
     $b_data = '';
     for ($i = 32; $i < 64; $i++) {
         $b_data .= chr($i);
     }
     $c_data = '';
     for ($i = 64; $i < 80; $i++) {
         $c_data .= chr($i);
     }
     $result = ByteUtil::split($data, 32, 32, 16);
     $this->assertEquals($result[0], $a_data);
     $this->assertEquals($result[1], $b_data);
     $this->assertEquals($result[2], $c_data);
 }
 public function DerivedRootSecrets($okm)
 {
     $keys = ByteUtil::split($okm, 32, 32);
     $this->rootKey = $keys[0];
     $this->chainKey = $keys[1];
 }
Esempio n. 8
0
 public function verifyMac($messageVersion, $senderIdentityKey, $receiverIdentityKey, $macKey)
 {
     $parts = ByteUtil::split($this->serialized, strlen($this->serialized) - self::MAC_LENGTH, self::MAC_LENGTH);
     $ourMac = $this->getMac($messageVersion, $senderIdentityKey, $receiverIdentityKey, $macKey, $parts[0]);
     $theirMac = $parts[1];
     if (strcmp($ourMac, $theirMac) != 0) {
         throw new InvalidMessageException("Bad Mac!");
     }
 }