protected function parseTreeUpdateResponse(Channel $chan, array $response) : array
{
if (!empty($response['no_updates'])) {
// The "no updates" message should be authenticated.
$signatureVerified = AsymmetricCrypto::verify($response['no_updates'], $chan->getPublicKey(), Base64UrlSafe::decode($response['signature']), true);
if (!$signatureVerified) {
throw new ChannelSignatureFailed();
}
$datetime = new \DateTime($response['no_updates']);
// One day ago:
$stale = (new \DateTime('now'))->sub(new \DateInterval('P01D'));
if ($datetime < $stale) {
throw new CouldNotUpdate(\__('Stale response.'));
}
// We got nothing to do:
return [];
}
// We were given updates. Let's validate them!
$TreeUpdateArray = [];
foreach ($response['updates'] as $update) {
$data = Base64UrlSafe::decode($update['data']);
$sig = Base64UrlSafe::decode($update['signature']);
$signatureVerified = AsymmetricCrypto::verify($data, $chan->getPublicKey(), $sig, true);
if (!$signatureVerified) {
// Invalid signature
throw new ChannelSignatureFailed();
}
// Now that we know it was signed by the channel, time to update
$TreeUpdateArray[] = new TreeUpdate($chan, \json_decode($data, true));
}
// Sort by ID
\uasort($TreeUpdateArray, function (TreeUpdate $a, TreeUpdate $b) : int {
return (int) ($a->getChannelId() <=> $b->getChannelId());
});
return $TreeUpdateArray;
}