From 4a08ff273bd89fcd014e4bc2d4e9735f1e441668 Mon Sep 17 00:00:00 2001 From: moesjarraf Date: Wed, 11 Nov 2015 03:38:10 +0100 Subject: [PATCH] Seperate decryption process from verifying process --- README.md | 21 ++++++++++++-- src/Authorizer.php | 68 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 1baa8f9..dbfc562 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ The library can be installed using composer. Add the following to your `composer ## Usage +**System A (Has resources which require authorization)** ``` php use LegalThings/Authorizer; @@ -46,13 +47,29 @@ class FooController } if (isset($_GET['authz']) { - $mayAccess = Authorizer::verify('/some/resource', $_GET['authz'], 'path/to/private_key.pem'); // authz is the encrypted secret + $mayAccess = Authorizer::verify('/some/resource', $_GET['authz']); // authz is the decrypted secret if (!$mayAccess) return $this->forbidden(); + $this->output($foo); } + } +} +``` + +**System B (Wants resources from system A)** +``` php +use LegalThings/Authorizer; +class Requester +{ + public function requestFooAction($id) + { ... + + $encryptedSecret = FooService::requestPermission('/some/resource', 'http://requester.localhost/public.pem', $startTime, $endTime); // this request fills up the authzgen in system A. Also, times are unix timestamps + + $decryptedSecret = Authorizer::decrypt($encryptedSecret, 'path/to/private_key.pem'); // this request fills up authz in system A + $foo = FooService::trustedRequest('/some/resource', $decryptedSecret); } } - ``` diff --git a/src/Authorizer.php b/src/Authorizer.php index 8ed5e04..e4d6f33 100644 --- a/src/Authorizer.php +++ b/src/Authorizer.php @@ -16,11 +16,12 @@ class Authorizer /** * Sign a resource, granting access to a specific client * - * @param string $resource - * @param string $authzgen String with the format: {{certificate_url}};{{time_from}};{{time_to}} - * Time restrictions are unix timestamps, but may be omitted + * @param string $allowedResource + * @param string $authzgen String with the format: {{certificate_url}};{{time_from}};{{time_to}} + * Time restrictions are unix timestamps, but may be omitted + * @return string $encryptedSecret */ - public static function sign($resource, $authzgen) + public static function sign($allowedResource, $authzgen) { if (!isset(self::$globalSecret)) trigger_error('$globalSecret is not set', E_USER_WARNING); @@ -29,10 +30,9 @@ public static function sign($resource, $authzgen) $publicKey = self::downloadPublicKey($cerfiticateUrl); $resourceSecret = join(';', [ - $resource, $timeStart, $timeEnd, - hash('sha256', $resource . $_SERVER['HTTP_HOST'] . $timeStart . $timeEnd . self::$globalSecret) + self::generateChecksum($allowedResource, $timeStart, $timeEnd) ]); openssl_public_encrypt($resourceSecret, $encryptedSecret, $publicKey); @@ -41,35 +41,67 @@ public static function sign($resource, $authzgen) } /** - * Verify if a resource may be accessed by the client by decrypting a secret + * Verify if a resource may be accessed by the client * - * @param string $allowedResource - * @param string $authz An encrypted secret with the format: - * {{resource}};{{time_from}};{{time_to}};{{hash}} - * @param string $privateKeyPath Path to the private key of the current application + * @param string $allowedResource + * @param string $decryptedSecret can be retrieved with static::decrypt() + * + * @return boolean */ - public static function verify($allowedResource, $authz, $privateKeyPath) + public static function verify($allowedResource, $decryptedSecret) { $currentTime = time(); - $privateKey = file_get_contents($privateKeyPath); - openssl_private_decrypt($authz, $decryptedSecret, $privateKey); - list($resource, $timeStart, $timeEnd) = explode(';', $decryptedSecret) + [null, null, null]; + list($timeStart, $timeEnd, $checksum) = explode(';', $decryptedSecret) + [null, null, null]; + + if ($checksum !== self::generateChecksum($allowedResource, $timeStart, $timeEnd) return false; $timeStart = strlen($timeStart) > 0 ? (int)$timeStart : ($currentTime - 1); $timeEnd = strlen($timeEnd) > 0 ? (int)$timeEnd : ($currentTime + 1); - if ($resource !== $allowedResource) return false; if ($currentTime < $timeStart || $currentTime > $timeEnd) return false; return true; } + /** + * Generates a checksum + * + * @param string $allowedResource + * @param string $timeStart + * @param string $timeEnd + * + * @return string + */ + private static function generateChecksum($allowedResource, $timeStart, $timeEnd) + { + return hash('sha256', $allowedResource . $_SERVER['HTTP_HOST'] . $timeStart . $timeEnd . self::$globalSecret) + } + + /** + * Decrypt an encrypted secret + * + * @param string $encryptedSecret An encrypted secret with the format: + * {{resource}};{{time_from}};{{time_to}};{{hash}} + * @param string $privateKeyPath Path to the private key of the current application + * + * @return string $decryptedSecret String with the format: {{time_from}};{{time_to}};{{checksum}} + */ + public static function decrypt($encryptedSecret, $privateKeyPath) + { + $privateKey = file_get_contents($privateKeyPath); + openssl_private_decrypt($encryptedSecret, $decryptedSecret, $privateKey); + + return $decryptedSecret; + } + /** * Get a public key through a remote url * - * @param string $url - * @param string $options Options for the guzzle request + * @param string $url + * @param string $options Options for the guzzle request + * + * @return string */ private static function downloadPublicKey($url, $options = []) {