Cleanup OAuth1 library
authorPhilipp <admin@philipp.info>
Wed, 30 Sep 2020 09:26:52 +0000 (11:26 +0200)
committerPhilipp <admin@philipp.info>
Wed, 30 Sep 2020 09:26:52 +0000 (11:26 +0200)
12 files changed:
src/Security/FKOAuth1.php
src/Security/OAuth1/OAuthRequest.php
src/Security/OAuth1/OAuthServer.php
src/Security/OAuth1/OAuthSignatureMethod.php [deleted file]
src/Security/OAuth1/OAuthSignatureMethod_HMAC_SHA1.php [deleted file]
src/Security/OAuth1/OAuthSignatureMethod_PLAINTEXT.php [deleted file]
src/Security/OAuth1/OAuthSignatureMethod_RSA_SHA1.php [deleted file]
src/Security/OAuth1/OAuthToken.php
src/Security/OAuth1/Signature/OAuthSignatureMethod.php [new file with mode: 0644]
src/Security/OAuth1/Signature/OAuthSignatureMethod_HMAC_SHA1.php [new file with mode: 0644]
src/Security/OAuth1/Signature/OAuthSignatureMethod_PLAINTEXT.php [new file with mode: 0644]
src/Security/OAuth1/Signature/OAuthSignatureMethod_RSA_SHA1.php [new file with mode: 0644]

index 1c9a38e..df6b38a 100644 (file)
@@ -25,8 +25,8 @@ use Friendica\Core\Logger;
 use Friendica\Database\DBA;
 use Friendica\DI;
 use Friendica\Security\OAuth1\OAuthServer;
-use Friendica\Security\OAuth1\OAuthSignatureMethod_HMAC_SHA1;
-use Friendica\Security\OAuth1\OAuthSignatureMethod_PLAINTEXT;
+use Friendica\Security\OAuth1\Signature\OAuthSignatureMethod_HMAC_SHA1;
+use Friendica\Security\OAuth1\Signature\OAuthSignatureMethod_PLAINTEXT;
 
 /**
  * OAuth protocol
index c578b2c..a4ceda7 100644 (file)
@@ -2,8 +2,7 @@
 
 namespace Friendica\Security\OAuth1;
 
-use Friendica;
-use Friendica\Security\OAuth1\OAuthUtil;
+use Friendica\Util\Strings;
 
 class OAuthRequest
 {
@@ -92,15 +91,15 @@ class OAuthRequest
        /**
         * pretty much a helper function to set up the request
         *
-        * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
-        * @param \Friendica\Security\OAuth1\OAuthToken    $token
-        * @param string                                   $http_method
-        * @param string                                   $http_url
-        * @param array|null                               $parameters
+        * @param OAuthConsumer $consumer
+        * @param OAuthToken    $token
+        * @param string        $http_method
+        * @param string        $http_url
+        * @param array|null    $parameters
         *
         * @return OAuthRequest
         */
-       public static function from_consumer_and_token(\Friendica\Security\OAuth1\OAuthConsumer $consumer, $http_method, $http_url, array $parameters = null, \Friendica\Security\OAuth1\OAuthToken $token = null)
+       public static function from_consumer_and_token(OAuthConsumer $consumer, $http_method, $http_url, array $parameters = null, OAuthToken $token = null)
        {
                @$parameters or $parameters = [];
                $defaults = [
@@ -252,7 +251,7 @@ class OAuthRequest
         * @param string|null $realm
         *
         * @return string
-        * @throws \Friendica\Security\OAuth1\OAuthException
+        * @throws OAuthException
         */
        public function to_header($realm = null)
        {
@@ -266,7 +265,7 @@ class OAuthRequest
                foreach ($this->parameters as $k => $v) {
                        if (substr($k, 0, 5) != "oauth") continue;
                        if (is_array($v)) {
-                               throw new \Friendica\Security\OAuth1\OAuthException('Arrays not supported in headers');
+                               throw new OAuthException('Arrays not supported in headers');
                        }
                        $out   .= ($first) ? ' ' : ',';
                        $out   .= OAuthUtil::urlencode_rfc3986($k) .
@@ -284,7 +283,7 @@ class OAuthRequest
        }
 
 
-       public function sign_request(\Friendica\Security\OAuth1\OAuthSignatureMethod $signature_method, $consumer, $token)
+       public function sign_request(Signature\OAuthSignatureMethod $signature_method, $consumer, $token)
        {
                $this->set_parameter(
                        "oauth_signature_method",
@@ -295,7 +294,7 @@ class OAuthRequest
                $this->set_parameter("oauth_signature", $signature, false);
        }
 
-       public function build_signature(\Friendica\Security\OAuth1\OAuthSignatureMethod $signature_method, $consumer, $token)
+       public function build_signature(Signature\OAuthSignatureMethod $signature_method, $consumer, $token)
        {
                $signature = $signature_method->build_signature($this, $consumer, $token);
                return $signature;
@@ -314,6 +313,6 @@ class OAuthRequest
         */
        private static function generate_nonce()
        {
-               return Friendica\Util\Strings::getRandomHex(32);
+               return Strings::getRandomHex(32);
        }
-}
\ No newline at end of file
+}
index 191fd8c..c8884f6 100644 (file)
@@ -3,16 +3,13 @@
 namespace Friendica\Security\OAuth1;
 
 use Friendica\Security\FKOAuthDataStore;
-use OAuthConsumer;
-use OAuthRequest;
-use OAuthSignatureMethod;
-use OAuthToken;
+use Friendica\Security\OAuth1\Signature;
 
 class OAuthServer
 {
        protected $timestamp_threshold = 300; // in seconds, five minutes
        protected $version = '1.0';             // hi blaine
-       /** @var \Friendica\Security\OAuth1\OAuthSignatureMethod[] */
+       /** @var Signature\OAuthSignatureMethod[] */
        protected $signature_methods = [];
 
        /** @var FKOAuthDataStore */
@@ -23,7 +20,7 @@ class OAuthServer
                $this->data_store = $data_store;
        }
 
-       public function add_signature_method(\Friendica\Security\OAuth1\OAuthSignatureMethod $signature_method)
+       public function add_signature_method(Signature\OAuthSignatureMethod $signature_method)
        {
                $this->signature_methods[$signature_method->get_name()] =
                        $signature_method;
@@ -35,12 +32,12 @@ class OAuthServer
         * process a request_token request
         * returns the request token on success
         *
-        * @param \Friendica\Security\OAuth1\OAuthRequest $request
+        * @param OAuthRequest $request
         *
-        * @return \Friendica\Security\OAuth1\OAuthToken|null
+        * @return OAuthToken|null
         * @throws OAuthException
         */
-       public function fetch_request_token(\Friendica\Security\OAuth1\OAuthRequest $request)
+       public function fetch_request_token(OAuthRequest $request)
        {
                $this->get_version($request);
 
@@ -62,12 +59,12 @@ class OAuthServer
         * process an access_token request
         * returns the access token on success
         *
-        * @param \Friendica\Security\OAuth1\OAuthRequest $request
+        * @param OAuthRequest $request
         *
         * @return object
         * @throws OAuthException
         */
-       public function fetch_access_token(\Friendica\Security\OAuth1\OAuthRequest $request)
+       public function fetch_access_token(OAuthRequest $request)
        {
                $this->get_version($request);
 
@@ -88,12 +85,12 @@ class OAuthServer
        /**
         * verify an api call, checks all the parameters
         *
-        * @param \Friendica\Security\OAuth1\OAuthRequest $request
+        * @param OAuthRequest $request
         *
         * @return array
         * @throws OAuthException
         */
-       public function verify_request(\Friendica\Security\OAuth1\OAuthRequest $request)
+       public function verify_request(OAuthRequest $request)
        {
                $this->get_version($request);
                $consumer = $this->get_consumer($request);
@@ -107,12 +104,12 @@ class OAuthServer
        /**
         * version 1
         *
-        * @param \Friendica\Security\OAuth1\OAuthRequest $request
+        * @param OAuthRequest $request
         *
         * @return string
         * @throws OAuthException
         */
-       private function get_version(\Friendica\Security\OAuth1\OAuthRequest $request)
+       private function get_version(OAuthRequest $request)
        {
                $version = $request->get_parameter("oauth_version");
                if (!$version) {
@@ -129,12 +126,12 @@ class OAuthServer
        /**
         * figure out the signature with some defaults
         *
-        * @param \Friendica\Security\OAuth1\OAuthRequest $request
+        * @param OAuthRequest $request
         *
-        * @return \Friendica\Security\OAuth1\OAuthSignatureMethod
+        * @return Signature\OAuthSignatureMethod
         * @throws OAuthException
         */
-       private function get_signature_method(\Friendica\Security\OAuth1\OAuthRequest $request)
+       private function get_signature_method(OAuthRequest $request)
        {
                $signature_method =
                        @$request->get_parameter("oauth_signature_method");
@@ -161,12 +158,12 @@ class OAuthServer
        /**
         * try to find the consumer for the provided request's consumer key
         *
-        * @param \Friendica\Security\OAuth1\OAuthRequest $request
+        * @param OAuthRequest $request
         *
-        * @return \Friendica\Security\OAuth1\OAuthConsumer
+        * @return OAuthConsumer
         * @throws OAuthException
         */
-       private function get_consumer(\Friendica\Security\OAuth1\OAuthRequest $request)
+       private function get_consumer(OAuthRequest $request)
        {
                $consumer_key = @$request->get_parameter("oauth_consumer_key");
                if (!$consumer_key) {
@@ -184,14 +181,14 @@ class OAuthServer
        /**
         * try to find the token for the provided request's token key
         *
-        * @param \Friendica\Security\OAuth1\OAuthRequest $request
+        * @param OAuthRequest                            $request
         * @param                                         $consumer
         * @param string                                  $token_type
         *
-        * @return \Friendica\Security\OAuth1\OAuthToken|null
+        * @return OAuthToken|null
         * @throws OAuthException
         */
-       private function get_token(\Friendica\Security\OAuth1\OAuthRequest &$request, $consumer, $token_type = "access")
+       private function get_token(OAuthRequest &$request, $consumer, $token_type = "access")
        {
                $token_field = @$request->get_parameter('oauth_token');
                $token       = $this->data_store->lookup_token(
@@ -209,13 +206,13 @@ class OAuthServer
         * all-in-one function to check the signature on a request
         * should guess the signature method appropriately
         *
-        * @param \Friendica\Security\OAuth1\OAuthRequest    $request
-        * @param \Friendica\Security\OAuth1\OAuthConsumer   $consumer
-        * @param \Friendica\Security\OAuth1\OAuthToken|null $token
+        * @param OAuthRequest    $request
+        * @param OAuthConsumer   $consumer
+        * @param OAuthToken|null $token
         *
         * @throws OAuthException
         */
-       private function check_signature(\Friendica\Security\OAuth1\OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
+       private function check_signature(OAuthRequest $request, OAuthConsumer $consumer, OAuthToken $token = null)
        {
                // this should probably be in a different method
                $timestamp = @$request->get_parameter('oauth_timestamp');
@@ -265,14 +262,14 @@ class OAuthServer
        /**
         * check that the nonce is not repeated
         *
-        * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
-        * @param \Friendica\Security\OAuth1\OAuthToken    $token
-        * @param string                                   $nonce
-        * @param int                                      $timestamp
+        * @param OAuthConsumer $consumer
+        * @param OAuthToken    $token
+        * @param string        $nonce
+        * @param int           $timestamp
         *
         * @throws OAuthException
         */
-       private function check_nonce(\Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token, $nonce, int $timestamp)
+       private function check_nonce(OAuthConsumer $consumer, OAuthToken $token, $nonce, int $timestamp)
        {
                if (!$nonce)
                        throw new OAuthException(
diff --git a/src/Security/OAuth1/OAuthSignatureMethod.php b/src/Security/OAuth1/OAuthSignatureMethod.php
deleted file mode 100644 (file)
index ac44230..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\OAuth1\OAuthRequest;
-
-/**
- * A class for implementing a Signature Method
- * See section 9 ("Signing Requests") in the spec
- */
-abstract class OAuthSignatureMethod
-{
-       /**
-        * Needs to return the name of the Signature Method (ie HMAC-SHA1)
-        *
-        * @return string
-        */
-       abstract public function get_name();
-
-       /**
-        * Build up the signature
-        * NOTE: The output of this function MUST NOT be urlencoded.
-        * the encoding is handled in OAuthRequest when the final
-        * request is serialized
-        *
-        * @param OAuthRequest                             $request
-        * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
-        * @param \Friendica\Security\OAuth1\OAuthToken    $token
-        *
-        * @return string
-        */
-       abstract public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null);
-
-       /**
-        * Verifies that a given signature is correct
-        *
-        * @param OAuthRequest                             $request
-        * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
-        * @param \Friendica\Security\OAuth1\OAuthToken    $token
-        * @param string                                   $signature
-        *
-        * @return bool
-        */
-       public function check_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, $signature, \Friendica\Security\OAuth1\OAuthToken $token = null)
-       {
-               $built = $this->build_signature($request, $consumer, $token);
-               return ($built == $signature);
-       }
-}
diff --git a/src/Security/OAuth1/OAuthSignatureMethod_HMAC_SHA1.php b/src/Security/OAuth1/OAuthSignatureMethod_HMAC_SHA1.php
deleted file mode 100644 (file)
index 286db08..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\OAuth1\OAuthRequest;
-use Friendica\Security\OAuth1\OAuthUtil;
-
-/**
- * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
- * where the Signature Base String is the text and the key is the concatenated values (each first
- * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
- * character (ASCII code 38) even if empty.
- *   - Chapter 9.2 ("HMAC-SHA1")
- */
-class OAuthSignatureMethod_HMAC_SHA1 extends \Friendica\Security\OAuth1\OAuthSignatureMethod
-{
-       function get_name()
-       {
-               return "HMAC-SHA1";
-       }
-
-       /**
-        * @param OAuthRequest                             $request
-        * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
-        * @param \Friendica\Security\OAuth1\OAuthToken    $token
-        *
-        * @return string
-        */
-       public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
-       {
-               $base_string          = $request->get_signature_base_string();
-               $request->base_string = $base_string;
-
-               $key_parts = [
-                       $consumer->secret,
-                       ($token) ? $token->secret : "",
-               ];
-
-               $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
-               $key       = implode('&', $key_parts);
-
-
-               $r = base64_encode(hash_hmac('sha1', $base_string, $key, true));
-               return $r;
-       }
-}
diff --git a/src/Security/OAuth1/OAuthSignatureMethod_PLAINTEXT.php b/src/Security/OAuth1/OAuthSignatureMethod_PLAINTEXT.php
deleted file mode 100644 (file)
index 29cb8cb..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\OAuth1\OAuthRequest;
-use Friendica\Security\OAuth1\OAuthUtil;
-
-/**
- * The PLAINTEXT method does not provide any security protection and SHOULD only be used
- * over a secure channel such as HTTPS. It does not use the Signature Base String.
- *   - Chapter 9.4 ("PLAINTEXT")
- */
-class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod
-{
-       public function get_name()
-       {
-               return "PLAINTEXT";
-       }
-
-       /**
-        * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
-        * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
-        * empty. The result MUST be encoded again.
-        *   - Chapter 9.4.1 ("Generating Signatures")
-        *
-        * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
-        * OAuthRequest handles this!
-        *
-        * @param $request
-        * @param $consumer
-        * @param $token
-        *
-        * @return string
-        */
-       public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
-       {
-               $key_parts = [
-                       $consumer->secret,
-                       ($token) ? $token->secret : "",
-               ];
-
-               $key_parts            = OAuthUtil::urlencode_rfc3986($key_parts);
-               $key                  = implode('&', $key_parts);
-               $request->base_string = $key;
-
-               return $key;
-       }
-}
diff --git a/src/Security/OAuth1/OAuthSignatureMethod_RSA_SHA1.php b/src/Security/OAuth1/OAuthSignatureMethod_RSA_SHA1.php
deleted file mode 100644 (file)
index 7d07f33..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\OAuth1\OAuthRequest;
-
-/**
- * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
- * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
- * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
- * verified way to the Service Provider, in a manner which is beyond the scope of this
- * specification.
- *   - Chapter 9.3 ("RSA-SHA1")
- */
-abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod
-{
-       public function get_name()
-       {
-               return "RSA-SHA1";
-       }
-
-       // Up to the SP to implement this lookup of keys. Possible ideas are:
-       // (1) do a lookup in a table of trusted certs keyed off of consumer
-       // (2) fetch via http using a url provided by the requester
-       // (3) some sort of specific discovery code based on request
-       //
-       // Either way should return a string representation of the certificate
-       protected abstract function fetch_public_cert(&$request);
-
-       // Up to the SP to implement this lookup of keys. Possible ideas are:
-       // (1) do a lookup in a table of trusted certs keyed off of consumer
-       //
-       // Either way should return a string representation of the certificate
-       protected abstract function fetch_private_cert(&$request);
-
-       public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
-       {
-               $base_string          = $request->get_signature_base_string();
-               $request->base_string = $base_string;
-
-               // Fetch the private key cert based on the request
-               $cert = $this->fetch_private_cert($request);
-
-               // Pull the private key ID from the certificate
-               $privatekeyid = openssl_get_privatekey($cert);
-
-               // Sign using the key
-               openssl_sign($base_string, $signature, $privatekeyid);
-
-               // Release the key resource
-               openssl_free_key($privatekeyid);
-
-               return base64_encode($signature);
-       }
-
-       public function check_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, $signature, \Friendica\Security\OAuth1\OAuthToken $token = null)
-       {
-               $decoded_sig = base64_decode($signature);
-
-               $base_string = $request->get_signature_base_string();
-
-               // Fetch the public key cert based on the request
-               $cert = $this->fetch_public_cert($request);
-
-               // Pull the public key ID from the certificate
-               $publickeyid = openssl_get_publickey($cert);
-
-               // Check the computed signature against the one passed in the query
-               $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
-
-               // Release the key resource
-               openssl_free_key($publickeyid);
-
-               return $ok == 1;
-       }
-}
index ef01cfc..749229e 100644 (file)
@@ -2,8 +2,6 @@
 
 namespace Friendica\Security\OAuth1;
 
-use Friendica\Security\OAuth1\OAuthUtil;
-
 class OAuthToken
 {
        // access tokens and request tokens
diff --git a/src/Security/OAuth1/Signature/OAuthSignatureMethod.php b/src/Security/OAuth1/Signature/OAuthSignatureMethod.php
new file mode 100644 (file)
index 0000000..52b1063
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+namespace Friendica\Security\OAuth1\Signature;
+
+use Friendica\Security\OAuth1\OAuthRequest;
+
+/**
+ * A class for implementing a Signature Method
+ * See section 9 ("Signing Requests") in the spec
+ */
+abstract class OAuthSignatureMethod
+{
+       /**
+        * Needs to return the name of the Signature Method (ie HMAC-SHA1)
+        *
+        * @return string
+        */
+       abstract public function get_name();
+
+       /**
+        * Build up the signature
+        * NOTE: The output of this function MUST NOT be urlencoded.
+        * the encoding is handled in OAuthRequest when the final
+        * request is serialized
+        *
+        * @param OAuthRequest                             $request
+        * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
+        * @param \Friendica\Security\OAuth1\OAuthToken    $token
+        *
+        * @return string
+        */
+       abstract public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null);
+
+       /**
+        * Verifies that a given signature is correct
+        *
+        * @param OAuthRequest                             $request
+        * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
+        * @param \Friendica\Security\OAuth1\OAuthToken    $token
+        * @param string                                   $signature
+        *
+        * @return bool
+        */
+       public function check_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, $signature, \Friendica\Security\OAuth1\OAuthToken $token = null)
+       {
+               $built = $this->build_signature($request, $consumer, $token);
+               return ($built == $signature);
+       }
+}
diff --git a/src/Security/OAuth1/Signature/OAuthSignatureMethod_HMAC_SHA1.php b/src/Security/OAuth1/Signature/OAuthSignatureMethod_HMAC_SHA1.php
new file mode 100644 (file)
index 0000000..b7afe1d
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+
+namespace Friendica\Security\OAuth1\Signature;
+
+use Friendica\Security\OAuth1\OAuthRequest;
+use Friendica\Security\OAuth1\OAuthUtil;
+
+/**
+ * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
+ * where the Signature Base String is the text and the key is the concatenated values (each first
+ * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
+ * character (ASCII code 38) even if empty.
+ *   - Chapter 9.2 ("HMAC-SHA1")
+ */
+class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod
+{
+       function get_name()
+       {
+               return "HMAC-SHA1";
+       }
+
+       /**
+        * @param OAuthRequest                             $request
+        * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
+        * @param \Friendica\Security\OAuth1\OAuthToken    $token
+        *
+        * @return string
+        */
+       public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
+       {
+               $base_string          = $request->get_signature_base_string();
+               $request->base_string = $base_string;
+
+               $key_parts = [
+                       $consumer->secret,
+                       ($token) ? $token->secret : "",
+               ];
+
+               $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
+               $key       = implode('&', $key_parts);
+
+
+               $r = base64_encode(hash_hmac('sha1', $base_string, $key, true));
+               return $r;
+       }
+}
diff --git a/src/Security/OAuth1/Signature/OAuthSignatureMethod_PLAINTEXT.php b/src/Security/OAuth1/Signature/OAuthSignatureMethod_PLAINTEXT.php
new file mode 100644 (file)
index 0000000..acf5e0e
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+namespace Friendica\Security\OAuth1\Signature;
+
+use Friendica\Security\OAuth1\OAuthRequest;
+use Friendica\Security\OAuth1\OAuthUtil;
+
+/**
+ * The PLAINTEXT method does not provide any security protection and SHOULD only be used
+ * over a secure channel such as HTTPS. It does not use the Signature Base String.
+ *   - Chapter 9.4 ("PLAINTEXT")
+ */
+class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod
+{
+       public function get_name()
+       {
+               return "PLAINTEXT";
+       }
+
+       /**
+        * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
+        * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
+        * empty. The result MUST be encoded again.
+        *   - Chapter 9.4.1 ("Generating Signatures")
+        *
+        * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
+        * OAuthRequest handles this!
+        *
+        * @param $request
+        * @param $consumer
+        * @param $token
+        *
+        * @return string
+        */
+       public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
+       {
+               $key_parts = [
+                       $consumer->secret,
+                       ($token) ? $token->secret : "",
+               ];
+
+               $key_parts            = OAuthUtil::urlencode_rfc3986($key_parts);
+               $key                  = implode('&', $key_parts);
+               $request->base_string = $key;
+
+               return $key;
+       }
+}
diff --git a/src/Security/OAuth1/Signature/OAuthSignatureMethod_RSA_SHA1.php b/src/Security/OAuth1/Signature/OAuthSignatureMethod_RSA_SHA1.php
new file mode 100644 (file)
index 0000000..1d60aad
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+
+namespace Friendica\Security\OAuth1\Signature;
+
+use Friendica\Security\OAuth1\OAuthRequest;
+
+/**
+ * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
+ * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
+ * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
+ * verified way to the Service Provider, in a manner which is beyond the scope of this
+ * specification.
+ *   - Chapter 9.3 ("RSA-SHA1")
+ */
+abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod
+{
+       public function get_name()
+       {
+               return "RSA-SHA1";
+       }
+
+       // Up to the SP to implement this lookup of keys. Possible ideas are:
+       // (1) do a lookup in a table of trusted certs keyed off of consumer
+       // (2) fetch via http using a url provided by the requester
+       // (3) some sort of specific discovery code based on request
+       //
+       // Either way should return a string representation of the certificate
+       protected abstract function fetch_public_cert(&$request);
+
+       // Up to the SP to implement this lookup of keys. Possible ideas are:
+       // (1) do a lookup in a table of trusted certs keyed off of consumer
+       //
+       // Either way should return a string representation of the certificate
+       protected abstract function fetch_private_cert(&$request);
+
+       public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
+       {
+               $base_string          = $request->get_signature_base_string();
+               $request->base_string = $base_string;
+
+               // Fetch the private key cert based on the request
+               $cert = $this->fetch_private_cert($request);
+
+               // Pull the private key ID from the certificate
+               $privatekeyid = openssl_get_privatekey($cert);
+
+               // Sign using the key
+               openssl_sign($base_string, $signature, $privatekeyid);
+
+               // Release the key resource
+               openssl_free_key($privatekeyid);
+
+               return base64_encode($signature);
+       }
+
+       public function check_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, $signature, \Friendica\Security\OAuth1\OAuthToken $token = null)
+       {
+               $decoded_sig = base64_decode($signature);
+
+               $base_string = $request->get_signature_base_string();
+
+               // Fetch the public key cert based on the request
+               $cert = $this->fetch_public_cert($request);
+
+               // Pull the public key ID from the certificate
+               $publickeyid = openssl_get_publickey($cert);
+
+               // Check the computed signature against the one passed in the query
+               $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
+
+               // Release the key resource
+               openssl_free_key($publickeyid);
+
+               return $ok == 1;
+       }
+}