protected function parseChannelUpdateResponse(array $data, \DateTime $originated) : array
{
if ($data['status'] !== 'success') {
throw new CouldNotUpdate($data['message'] ?? \__('An update error has occurred'));
}
$valid = [];
if (!empty($data['no_updates'])) {
// Verify signature of the "no updates" timestamp.
$sig = Base64UrlSafe::decode($data['signature']);
if (!AsymmetricCrypto::verify($data['no_updates'], $this->channelPublicKey, $sig, true)) {
throw new CouldNotUpdate(\__('Invalid signature from channel'));
}
$time = (new \DateTime($data['no_updates']))->add(new \DateInterval('P01D'));
if ($time < $originated) {
throw new CouldNotUpdate(\__('Channel is reporting a stale "no update" status'));
}
// No updates.
return [];
}
// Verify the signature of each update.
foreach ($data['updates'] as $update) {
$data = Base64UrlSafe::decode($update['data']);
$sig = Base64UrlSafe::decode($update['signature']);
if (AsymmetricCrypto::verify($data, $this->channelPublicKey, $sig, true)) {
$dataInternal = \json_decode($data, true);
$valid[] = ['id' => (int) $update['id'], 'stored' => $dataInternal['stored'], 'master_signature' => $dataInternal['master_signature'], 'root' => $dataInternal['root'], 'data' => $dataInternal['data']];
}
}
// Sort by ID
\uasort($valid, function (array $a, array $b) : int {
return (int) ($a['id'] <=> $b['id']);
});
return $valid;
}