From 6fc9c6de3b99aa01212d29ea0d140334d4e38396 Mon Sep 17 00:00:00 2001 From: Adam Magness 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 ''; } 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 ''; - $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));