From 6fc9c6de3b99aa01212d29ea0d140334d4e38396 Mon Sep 17 00:00:00 2001
From: Adam Magness <adam.magness@gmail.com>
Date: Thu, 8 Nov 2018 10:37:08 -0500
Subject: [PATCH] base64url calls

implement base64UrlEncode and base64UrlDecode functions
---
 mod/salmon.php            | 10 +++++-----
 spec/zot-2012.txt         |  4 ++--
 src/Content/OEmbed.php    |  3 ++-
 src/Content/Smilies.php   |  5 +++--
 src/Module/Magic.php      |  2 +-
 src/Module/Oembed.php     |  3 ++-
 src/Module/Owa.php        |  2 +-
 src/Network/Probe.php     |  4 ++--
 src/Protocol/DFRN.php     |  4 ++--
 src/Protocol/Diaspora.php | 30 +++++++++++++++---------------
 src/Protocol/Salmon.php   | 17 +++++++++--------
 src/Util/Crypto.php       | 33 +++++++++++++++++----------------
 src/Util/Strings.php      |  6 +++---
 13 files changed, 64 insertions(+), 59 deletions(-)

diff --git a/mod/salmon.php b/mod/salmon.php
index e549b3d0f8..1538a1c68c 100644
--- a/mod/salmon.php
+++ b/mod/salmon.php
@@ -58,7 +58,7 @@ function salmon_post(App $a, $xml = '') {
 	// Stash the signature away for now. We have to find their key or it won't be good for anything.
 
 
-	$signature = base64url_decode($base->sig);
+	$signature = Strings::base64UrlDecode($base->sig);
 
 	// unpack the  data
 
@@ -77,13 +77,13 @@ function salmon_post(App $a, $xml = '') {
 
 	$stnet_signed_data = $data;
 
-	$signed_data = $data  . '.' . base64url_encode($type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($alg);
+	$signed_data = $data  . '.' . Strings::base64UrlEncode($type) . '.' . Strings::base64UrlEncode($encoding) . '.' . Strings::base64UrlEncode($alg);
 
 	$compliant_format = str_replace('=', '', $signed_data);
 
 
 	// decode the data
-	$data = base64url_decode($data);
+	$data = Strings::base64UrlDecode($data);
 
 	$author = OStatus::salmonAuthor($data, $importer);
 	$author_link = $author["author-link"];
@@ -106,8 +106,8 @@ function salmon_post(App $a, $xml = '') {
 
 	$key_info = explode('.',$key);
 
-	$m = base64url_decode($key_info[1]);
-	$e = base64url_decode($key_info[2]);
+	$m = Strings::base64UrlDecode($key_info[1]);
+	$e = Strings::base64UrlDecode($key_info[2]);
 
 	Logger::log('key details: ' . print_r($key_info,true), Logger::DEBUG);
 
diff --git a/spec/zot-2012.txt b/spec/zot-2012.txt
index 2e1f3c3c49..3d939bab73 100644
--- a/spec/zot-2012.txt
+++ b/spec/zot-2012.txt
@@ -11,12 +11,12 @@ First create a global unique userid
 Site userid:
 https://macgirvin.com/1
 
-$guuid = base64url_encode(hash('whirlpool','https://macgirvin.com/1.' . mt_rand(1000000,9999999),1);
+$guuid = Strings::base64UrlEncode(hash('whirlpool','https://macgirvin.com/1.' . mt_rand(1000000,9999999),1);
 
 
 Then create a hashed site destination.
 
-$gduid = base64url_encode(hash('whirlpool', $guuid . 'https://macgirvin.com',1);
+$gduid = Strings::base64UrlEncode(hash('whirlpool', $guuid . 'https://macgirvin.com',1);
 
 These two keys will identify you as a person+site pair in the future.
 You will also obtain a password upon introducing yourself to a site.
diff --git a/src/Content/OEmbed.php b/src/Content/OEmbed.php
index 943b91e1f2..741f1f42d8 100644
--- a/src/Content/OEmbed.php
+++ b/src/Content/OEmbed.php
@@ -21,6 +21,7 @@ use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
 use Friendica\Util\ParseUrl;
 use Friendica\Util\Proxy as ProxyUtils;
+use Friendica\Util\Strings;
 
 require_once 'include/dba.php';
 
@@ -373,7 +374,7 @@ class OEmbed
 		}
 		$width = '100%';
 
-		$src = System::baseUrl() . '/oembed/' . base64url_encode($src);
+		$src = System::baseUrl() . '/oembed/' . Strings::base64UrlEncode($src);
 		return '<iframe onload="resizeIframe(this);" class="embed_rich" height="' . $height . '" width="' . $width . '" src="' . $src . '" allowfullscreen scrolling="no" frameborder="no">' . L10n::t('Embedded content') . '</iframe>';
 	}
 
diff --git a/src/Content/Smilies.php b/src/Content/Smilies.php
index 39de3c20e0..292841361e 100644
--- a/src/Content/Smilies.php
+++ b/src/Content/Smilies.php
@@ -19,6 +19,7 @@ use Friendica\Core\Addon;
 use Friendica\Core\Config;
 use Friendica\Core\PConfig;
 use Friendica\Core\System;
+use Friendica\Util\Strings;
 
 /**
  * This class contains functions to handle smiles
@@ -241,7 +242,7 @@ class Smilies
 	 */
 	private static function encode($m)
 	{
-		return(str_replace($m[1], base64url_encode($m[1]), $m[0]));
+		return(str_replace($m[1], Strings::base64UrlEncode($m[1]), $m[0]));
 	}
 
 	/**
@@ -251,7 +252,7 @@ class Smilies
 	 */
 	private static function decode($m)
 	{
-		return(str_replace($m[1], base64url_decode($m[1]), $m[0]));
+		return(str_replace($m[1], Strings::base64UrlDecode($m[1]), $m[0]));
 	}
 
 
diff --git a/src/Module/Magic.php b/src/Module/Magic.php
index 01c5d5d464..a94339a6e9 100644
--- a/src/Module/Magic.php
+++ b/src/Module/Magic.php
@@ -95,7 +95,7 @@ class Magic extends BaseModule
 						if ($j['encrypted_token']) {
 							// The token is encrypted. If the local user is really the one the other instance
 							// thinks he/she is, the token can be decrypted with the local users public key.
-							openssl_private_decrypt(base64url_decode($j['encrypted_token']), $token, $user['prvkey']);
+							openssl_private_decrypt(Strings::base64UrlDecode($j['encrypted_token']), $token, $user['prvkey']);
 						} else {
 							$token = $j['token'];
 						}
diff --git a/src/Module/Oembed.php b/src/Module/Oembed.php
index 452162ff20..9ca4530d8b 100644
--- a/src/Module/Oembed.php
+++ b/src/Module/Oembed.php
@@ -4,6 +4,7 @@ namespace Friendica\Module;
 
 use Friendica\BaseModule;
 use Friendica\Content;
+use Friendica\Util\Strings;
 
 /**
  * Oembed module
@@ -36,7 +37,7 @@ class Oembed extends BaseModule
 
 		if ($a->argc == 2) {
 			echo '<html><body>';
-			$url = base64url_decode($a->argv[1]);
+			$url = Strings::base64UrlDecode($a->argv[1]);
 			$j = Content\OEmbed::fetchURL($url);
 
 			// workaround for media.ccc.de (and any other endpoint that return size 0)
diff --git a/src/Module/Owa.php b/src/Module/Owa.php
index 8832dd9b0d..bfe108c842 100644
--- a/src/Module/Owa.php
+++ b/src/Module/Owa.php
@@ -75,7 +75,7 @@ class Owa extends BaseModule
 								// At a later time, we will compare weather the token we're getting
 								// is really the same token we have stored in the database.
 								openssl_public_encrypt($token, $result, $contact['pubkey']);
-								$ret['encrypted_token'] = base64url_encode($result);
+								$ret['encrypted_token'] = Strings::base64UrlEncode($result);
 							} else {
 								Logger::log('OWA fail: ' . $contact['id'] . ' ' . $contact['addr'] . ' ' . $contact['url'], Logger::DEBUG);
 							}
diff --git a/src/Network/Probe.php b/src/Network/Probe.php
index efd58e2b36..030de41299 100644
--- a/src/Network/Probe.php
+++ b/src/Network/Probe.php
@@ -1313,8 +1313,8 @@ class Probe
 					$key = explode(".", $pubkey);
 
 					if (sizeof($key) >= 3) {
-						$m = base64url_decode($key[1]);
-						$e = base64url_decode($key[2]);
+						$m = Strings::base64UrlDecode($key[1]);
+						$e = Strings::base64UrlDecode($key[2]);
 						$data["pubkey"] = Crypto::meToPem($m, $e);
 					}
 				}
diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index 96ed32010e..71ef636a3f 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -1002,7 +1002,7 @@ class DFRN
 		XML::addElement($doc, $entry, "updated", DateTimeFormat::utc($item["edited"] . "+00:00", DateTimeFormat::ATOM));
 
 		// "dfrn:env" is used to read the content
-		XML::addElement($doc, $entry, "dfrn:env", base64url_encode($body, true));
+		XML::addElement($doc, $entry, "dfrn:env", Strings::base64UrlEncode($body, true));
 
 		// The "content" field is not read by the receiver. We could remove it when the type is "text"
 		// We keep it at the moment, maybe there is some old version that doesn't read "dfrn:env"
@@ -2494,7 +2494,7 @@ class DFRN
 		$item["body"] = XML::getFirstNodeValue($xpath, "dfrn:env/text()", $entry);
 		$item["body"] = str_replace([' ',"\t","\r","\n"], ['','','',''], $item["body"]);
 		// make sure nobody is trying to sneak some html tags by us
-		$item["body"] = Strings::removeTags(base64url_decode($item["body"]));
+		$item["body"] = Strings::removeTags(Strings::base64UrlDecode($item["body"]));
 
 		$item["body"] = BBCode::limitBodySize($item["body"]);
 
diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php
index b552a415f2..39053c3937 100644
--- a/src/Protocol/Diaspora.php
+++ b/src/Protocol/Diaspora.php
@@ -298,23 +298,23 @@ class Diaspora
 
 		$handle = "";
 
-		$data = base64url_decode($children->data);
+		$data = Strings::base64UrlDecode($children->data);
 		$type = $children->data->attributes()->type[0];
 
 		$encoding = $children->encoding;
 
 		$alg = $children->alg;
 
-		$sig = base64url_decode($children->sig);
+		$sig = Strings::base64UrlDecode($children->sig);
 		$key_id = $children->sig->attributes()->key_id[0];
 		if ($key_id != "") {
-			$handle = base64url_decode($key_id);
+			$handle = Strings::base64UrlDecode($key_id);
 		}
 
-		$b64url_data = base64url_encode($data);
+		$b64url_data = Strings::base64UrlEncode($data);
 		$msg = str_replace(["\n", "\r", " ", "\t"], ["", "", "", ""], $b64url_data);
 
-		$signable_data = $msg.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
+		$signable_data = $msg.".".Strings::base64UrlEncode($type).".".Strings::base64UrlEncode($encoding).".".Strings::base64UrlEncode($alg);
 
 		if ($handle == '') {
 			Logger::log('No author could be decoded. Discarding. Message: ' . $envelope);
@@ -426,10 +426,10 @@ class Diaspora
 		$type = $base->data[0]->attributes()->type[0];
 		$encoding = $base->encoding;
 		$alg = $base->alg;
-		$signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg);
+		$signed_data = $data.'.'.Strings::base64UrlEncode($type).'.'.Strings::base64UrlEncode($encoding).'.'.Strings::base64UrlEncode($alg);
 
 		// This is the signature
-		$signature = base64url_decode($base->sig);
+		$signature = Strings::base64UrlDecode($base->sig);
 
 		// Get the senders' public key
 		$key_id = $base->sig[0]->attributes()->key_id[0];
@@ -463,7 +463,7 @@ class Diaspora
 			}
 		}
 
-		return ['message' => (string)base64url_decode($base->data),
+		return ['message' => (string)Strings::base64UrlDecode($base->data),
 				'author' => XML::unescape($author_addr),
 				'key' => (string)$key];
 	}
@@ -547,7 +547,7 @@ class Diaspora
 
 
 		// Stash the signature away for now. We have to find their key or it won't be good for anything.
-		$signature = base64url_decode($base->sig);
+		$signature = Strings::base64UrlDecode($base->sig);
 
 		// unpack the  data
 
@@ -563,11 +563,11 @@ class Diaspora
 		$alg = $base->alg;
 
 
-		$signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg);
+		$signed_data = $data.'.'.Strings::base64UrlEncode($type).'.'.Strings::base64UrlEncode($encoding).'.'.Strings::base64UrlEncode($alg);
 
 
 		// decode the data
-		$data = base64url_decode($data);
+		$data = Strings::base64UrlDecode($data);
 
 
 		if ($public) {
@@ -2962,14 +2962,14 @@ class Diaspora
 	 */
 	public static function buildMagicEnvelope($msg, array $user)
 	{
-		$b64url_data = base64url_encode($msg);
+		$b64url_data = Strings::base64UrlEncode($msg);
 		$data = str_replace(["\n", "\r", " ", "\t"], ["", "", "", ""], $b64url_data);
 
-		$key_id = base64url_encode(self::myHandle($user));
+		$key_id = Strings::base64UrlEncode(self::myHandle($user));
 		$type = "application/xml";
 		$encoding = "base64url";
 		$alg = "RSA-SHA256";
-		$signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
+		$signable_data = $data.".".Strings::base64UrlEncode($type).".".Strings::base64UrlEncode($encoding).".".Strings::base64UrlEncode($alg);
 
 		// Fallback if the private key wasn't transmitted in the expected field
 		if ($user['uprvkey'] == "") {
@@ -2977,7 +2977,7 @@ class Diaspora
 		}
 
 		$signature = Crypto::rsaSign($signable_data, $user["uprvkey"]);
-		$sig = base64url_encode($signature);
+		$sig = Strings::base64UrlEncode($signature);
 
 		$xmldata = ["me:env" => ["me:data" => $data,
 							"@attributes" => ["type" => $type],
diff --git a/src/Protocol/Salmon.php b/src/Protocol/Salmon.php
index 29abd77d06..1192781801 100644
--- a/src/Protocol/Salmon.php
+++ b/src/Protocol/Salmon.php
@@ -8,6 +8,7 @@ use Friendica\Core\Logger;
 use Friendica\Network\Probe;
 use Friendica\Util\Crypto;
 use Friendica\Util\Network;
+use Friendica\Util\Strings;
 use Friendica\Util\XML;
 
 /**
@@ -70,7 +71,7 @@ class Salmon
 			return $ret[0];
 		} else {
 			foreach ($ret as $a) {
-				$hash = base64url_encode(hash('sha256', $a));
+				$hash = Strings::base64UrlEncode(hash('sha256', $a));
 				if ($hash == $keyhash) {
 					return $a;
 				}
@@ -104,22 +105,22 @@ class Salmon
 
 		// create a magic envelope
 
-		$data      = base64url_encode($slap);
+		$data      = Strings::base64UrlEncode($slap);
 		$data_type = 'application/atom+xml';
 		$encoding  = 'base64url';
 		$algorithm = 'RSA-SHA256';
-		$keyhash   = base64url_encode(hash('sha256', self::salmonKey($owner['spubkey'])), true);
+		$keyhash   = Strings::base64UrlEncode(hash('sha256', self::salmonKey($owner['spubkey'])), true);
 
-		$precomputed = '.' . base64url_encode($data_type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($algorithm);
+		$precomputed = '.' . Strings::base64UrlEncode($data_type) . '.' . Strings::base64UrlEncode($encoding) . '.' . Strings::base64UrlEncode($algorithm);
 
 		// GNU Social format
-		$signature   = base64url_encode(Crypto::rsaSign($data . $precomputed, $owner['sprvkey']));
+		$signature   = Strings::base64UrlEncode(Crypto::rsaSign($data . $precomputed, $owner['sprvkey']));
 
 		// Compliant format
-		$signature2  = base64url_encode(Crypto::rsaSign(str_replace('=', '', $data . $precomputed), $owner['sprvkey']));
+		$signature2  = Strings::base64UrlEncode(Crypto::rsaSign(str_replace('=', '', $data . $precomputed), $owner['sprvkey']));
 
 		// Old Status.net format
-		$signature3  = base64url_encode(Crypto::rsaSign($data, $owner['sprvkey']));
+		$signature3  = Strings::base64UrlEncode(Crypto::rsaSign($data, $owner['sprvkey']));
 
 		// At first try the non compliant method that works for GNU Social
 		$xmldata = ["me:env" => ["me:data" => $data,
@@ -208,6 +209,6 @@ class Salmon
 	public static function salmonKey($pubkey)
 	{
 		Crypto::pemToMe($pubkey, $m, $e);
-		return 'RSA' . '.' . base64url_encode($m, true) . '.' . base64url_encode($e, true);
+		return 'RSA' . '.' . Strings::base64UrlEncode($m, true) . '.' . Strings::base64UrlEncode($e, true);
 	}
 }
diff --git a/src/Util/Crypto.php b/src/Util/Crypto.php
index 7dd0dee5c0..3426babe36 100644
--- a/src/Util/Crypto.php
+++ b/src/Util/Crypto.php
@@ -7,6 +7,7 @@ namespace Friendica\Util;
 use Friendica\Core\Addon;
 use Friendica\Core\Config;
 use Friendica\Core\Logger;
+use Friendica\Util\Strings;
 use ASN_BASE;
 use ASNValue;
 
@@ -159,8 +160,8 @@ class Crypto
 
 		$r = ASN_BASE::parseASNString($x);
 
-		$m = base64url_decode($r[0]->asnData[0]->asnData);
-		$e = base64url_decode($r[0]->asnData[1]->asnData);
+		$m = Strings::base64UrlDecode($r[0]->asnData[0]->asnData);
+		$e = Strings::base64UrlDecode($r[0]->asnData[1]->asnData);
 	}
 
 	/**
@@ -198,8 +199,8 @@ class Crypto
 
 		$r = ASN_BASE::parseASNString($x);
 
-		$m = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[0]->asnData);
-		$e = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[1]->asnData);
+		$m = Strings::base64UrlDecode($r[0]->asnData[1]->asnData[0]->asnData[0]->asnData);
+		$e = Strings::base64UrlDecode($r[0]->asnData[1]->asnData[0]->asnData[1]->asnData);
 	}
 
 	/**
@@ -355,7 +356,7 @@ class Crypto
 			$result = ['encrypted' => true];
 			$key = random_bytes(256);
 			$iv  = random_bytes(256);
-			$result['data'] = base64url_encode(self::$fn($data, $key, $iv), true);
+			$result['data'] = Strings::base64UrlEncode(self::$fn($data, $key, $iv), true);
 
 			// log the offending call so we can track it down
 			if (!openssl_public_encrypt($key, $k, $pubkey)) {
@@ -364,9 +365,9 @@ class Crypto
 			}
 
 			$result['alg'] = $alg;
-			$result['key'] = base64url_encode($k, true);
+			$result['key'] = Strings::base64UrlEncode($k, true);
 			openssl_public_encrypt($iv, $i, $pubkey);
-			$result['iv'] = base64url_encode($i, true);
+			$result['iv'] = Strings::base64UrlEncode($i, true);
 
 			return $result;
 		} else {
@@ -395,7 +396,7 @@ class Crypto
 		$key = random_bytes(32);
 		$iv  = random_bytes(16);
 		$result = ['encrypted' => true];
-		$result['data'] = base64url_encode(self::encryptAES256CBC($data, $key, $iv), true);
+		$result['data'] = Strings::base64UrlEncode(self::encryptAES256CBC($data, $key, $iv), true);
 
 		// log the offending call so we can track it down
 		if (!openssl_public_encrypt($key, $k, $pubkey)) {
@@ -404,9 +405,9 @@ class Crypto
 		}
 
 		$result['alg'] = 'aes256cbc';
-		$result['key'] = base64url_encode($k, true);
+		$result['key'] = Strings::base64UrlEncode($k, true);
 		openssl_public_encrypt($iv, $i, $pubkey);
-		$result['iv'] = base64url_encode($i, true);
+		$result['iv'] = Strings::base64UrlEncode($i, true);
 
 		return $result;
 	}
@@ -448,10 +449,10 @@ class Crypto
 		$fn = 'decrypt' . strtoupper($alg);
 
 		if (method_exists(__CLASS__, $fn)) {
-			openssl_private_decrypt(base64url_decode($data['key']), $k, $prvkey);
-			openssl_private_decrypt(base64url_decode($data['iv']), $i, $prvkey);
+			openssl_private_decrypt(Strings::base64UrlDecode($data['key']), $k, $prvkey);
+			openssl_private_decrypt(Strings::base64UrlDecode($data['iv']), $i, $prvkey);
 
-			return self::$fn(base64url_decode($data['data']), $k, $i);
+			return self::$fn(Strings::base64UrlDecode($data['data']), $k, $i);
 		} else {
 			$x = ['data' => $data, 'prvkey' => $prvkey, 'alg' => $alg, 'result' => $data];
 			Addon::callHooks('other_unencapsulate', $x);
@@ -471,10 +472,10 @@ class Crypto
 	 */
 	private static function unencapsulateAes($data, $prvkey)
 	{
-		openssl_private_decrypt(base64url_decode($data['key']), $k, $prvkey);
-		openssl_private_decrypt(base64url_decode($data['iv']), $i, $prvkey);
+		openssl_private_decrypt(Strings::base64UrlDecode($data['key']), $k, $prvkey);
+		openssl_private_decrypt(Strings::base64UrlDecode($data['iv']), $i, $prvkey);
 
-		return self::decryptAES256CBC(base64url_decode($data['data']), $k, $i);
+		return self::decryptAES256CBC(Strings::base64UrlDecode($data['data']), $k, $i);
 	}
 
 
diff --git a/src/Util/Strings.php b/src/Util/Strings.php
index 34ca143644..dbab71d352 100644
--- a/src/Util/Strings.php
+++ b/src/Util/Strings.php
@@ -220,7 +220,7 @@ class Strings
      * 
      * @return string   Transformed string.
      */
-    public static function protectSprintf($s) // protect_sprintf()
+    public static function protectSprintf($s)
     {
         return str_replace('%', '%%', $s);
     }
@@ -233,7 +233,7 @@ class Strings
      * 
      * @return string   Encoded URL
      */
-    public static function base64UrlEncode($s, $strip_padding = false) //base64url_encode()
+    public static function base64UrlEncode($s, $strip_padding = false)
     {
         $s = strtr(base64_encode($s), '+/', '-_');
 
@@ -250,7 +250,7 @@ class Strings
      * 
      * @return string   Decoded URL
      */
-    public static function base64url_decode($s) // base64url_decode()
+    public static function base64UrlDecode($s)
     {
         if (is_array($s)) {
             Logger::log('base64url_decode: illegal input: ' . print_r(debug_backtrace(), true));