/** * Let's get the latest package information from the mirror * * @param string $publickey Public key (base64 encoded) * @param string $secretkey Secret key (base64 encoded) * @param string $package (optional; defaults to grabbing all) * @return array */ public function updatePackageInfo($publickey, $secretkey, $package = null) { $requesting = []; if (!empty($package)) { // We just need the one $requesting[] = $package; } else { // Let's grab all the names foreach (self::$userConfig->get(['packages']) as $pkg) { $requesting[] = $pkg['name']; } } // We send off our public key, and get an encrypted response back. $apiResponse = $this->http->post($this->basepath . self::$api['package']['latest'], ['packages' => $requesting, 'publickey' => $publickey]); $api = \json_decode($apiResponse, true); if (!empty($api['error']) || empty($api['packages']) || empty($api['nonce']) || empty($api['publickey'])) { return false; } // We need to decrypt the response // Server's public key (can rotate) $serverPublicKey = \base64_decode($api['publickey']); // A nonce used to decrypt $serverNonce = \base64_decode($api['nonce']); // What packages are there? $ciphertext = \base64_decode($api['packages']); // Calculate symmetric encryption key $eBoxKey = \Sodium::crypto_box_keypair_from_secretkey_and_publickey($secretkey, \base64_decode($serverPublicKey)); // Let's grab our solution $updates = \Sodium::crypto_box_open($ciphertext, $serverNonce, $eBoxKey); // We want an array return \json_decode($updates, true); }
/** * * * @param array $block * @param array $validLicense */ private function extractBlockData($block, $validLicense) { if (\is_string($block) && \preg_match('#^p:#', $block)) { // Private package! // 'p' (for Private) // Client Public Key // Ephemeral Public Key // Nonce // Authenticated Ciphertext list(, $clientPublic, $serverPublic, $nonce, $ciphertext) = \explode(':', $block); if (!\hash_equals($clientPublic, $validLicense['publickey'])) { die("Public key didn't match. Decryption will fail!"); } $secretkey = \base64_decode($validLicense['secretkey']); $eBoxKey = \Sodium::crypto_box_keypair_from_secretkey_and_publickey($secretkey, \base64_decode($serverPublic)); $message = \Sodium::crypto_box_open(\base64_decode($ciphertext), \base64_decode($nonce), $eBoxKey); \Sodium::sodium_memzero($eBoxKey); if ($message === false) { die("Decryption failed!"); } return \json_decode($message, true); } return $block; }
/** * Helper method to handle challenge-response authentication. Just returns * the decrypted response. * * @param string $serverPublicKey * @param string $serverNonce * @param string $challenge * @param string $secretkey * @return string */ public static function challengeResponse($serverPublicKey, $serverNonce, $challenge, $secretkey) { $_serverPublicKey = \base64_decode($serverPublicKey); $_serverNonce = \base64_decode($serverNonce); $_challenge = \base64_decode($challenge); // Calculate symmetric encryption key $eBoxKey = \Sodium::crypto_box_keypair_from_secretkey_and_publickey($secretkey, $_serverPublicKey); // Let's grab our solution $result = \Sodium::crypto_box_open($_challenge, $_serverNonce, $eBoxKey); \Sodium::sodium_memzero($eBoxKey); return $result; }